2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "cl_dyntexture.h"
30 #include "dpsoftrast.h"
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
55 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
56 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
57 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
58 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
60 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
62 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
63 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
64 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
65 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
66 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
68 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
69 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
70 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
71 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
72 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
73 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
74 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
75 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
76 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
77 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
78 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
79 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
80 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
81 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
82 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
83 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
84 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
85 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
86 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
87 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
88 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
89 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
90 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
91 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
92 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
93 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
94 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
95 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
97 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
98 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
99 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
101 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
102 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
103 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
104 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
105 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
106 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
107 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
108 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
109 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
110 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
111 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
112 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
113 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
114 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
115 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
116 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
117 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
118 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
119 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
121 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
122 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
123 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
124 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
125 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
126 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
127 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
128 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
130 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
131 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
133 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
134 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
135 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
136 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
137 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
139 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
140 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
141 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
143 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
144 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
145 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
146 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
147 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
148 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
149 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
150 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
151 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
152 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
153 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
154 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
155 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
157 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
158 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
159 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
160 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
161 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
162 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
164 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
165 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
166 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
167 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
169 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
170 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
171 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
172 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
173 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
174 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
175 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
177 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
178 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
179 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
180 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivalent to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
181 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
182 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
183 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
184 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
185 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
186 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
188 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
190 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
192 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
194 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
195 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
196 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
197 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
198 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
199 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
200 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "15", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
201 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
202 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
204 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
205 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
207 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
209 extern cvar_t v_glslgamma;
211 extern qboolean v_flipped_state;
213 static struct r_bloomstate_s
218 int bloomwidth, bloomheight;
220 int screentexturewidth, screentextureheight;
221 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
223 int bloomtexturewidth, bloomtextureheight;
224 rtexture_t *texture_bloom;
226 // arrays for rendering the screen passes
227 float screentexcoord2f[8];
228 float bloomtexcoord2f[8];
229 float offsettexcoord2f[8];
231 r_viewport_t viewport;
235 r_waterstate_t r_waterstate;
237 /// shadow volume bsp struct with automatically growing nodes buffer
240 rtexture_t *r_texture_blanknormalmap;
241 rtexture_t *r_texture_white;
242 rtexture_t *r_texture_grey128;
243 rtexture_t *r_texture_black;
244 rtexture_t *r_texture_notexture;
245 rtexture_t *r_texture_whitecube;
246 rtexture_t *r_texture_normalizationcube;
247 rtexture_t *r_texture_fogattenuation;
248 rtexture_t *r_texture_fogheighttexture;
249 rtexture_t *r_texture_gammaramps;
250 unsigned int r_texture_gammaramps_serial;
251 //rtexture_t *r_texture_fogintensity;
252 rtexture_t *r_texture_reflectcube;
254 // TODO: hash lookups?
255 typedef struct cubemapinfo_s
262 int r_texture_numcubemaps;
263 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
265 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
266 unsigned int r_numqueries;
267 unsigned int r_maxqueries;
269 typedef struct r_qwskincache_s
271 char name[MAX_QPATH];
272 skinframe_t *skinframe;
276 static r_qwskincache_t *r_qwskincache;
277 static int r_qwskincache_size;
279 /// vertex coordinates for a quad that covers the screen exactly
280 extern const float r_screenvertex3f[12];
281 extern const float r_d3dscreenvertex3f[12];
282 const float r_screenvertex3f[12] =
289 const float r_d3dscreenvertex3f[12] =
297 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
300 for (i = 0;i < verts;i++)
311 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
314 for (i = 0;i < verts;i++)
324 // FIXME: move this to client?
327 if (gamemode == GAME_NEHAHRA)
329 Cvar_Set("gl_fogenable", "0");
330 Cvar_Set("gl_fogdensity", "0.2");
331 Cvar_Set("gl_fogred", "0.3");
332 Cvar_Set("gl_foggreen", "0.3");
333 Cvar_Set("gl_fogblue", "0.3");
335 r_refdef.fog_density = 0;
336 r_refdef.fog_red = 0;
337 r_refdef.fog_green = 0;
338 r_refdef.fog_blue = 0;
339 r_refdef.fog_alpha = 1;
340 r_refdef.fog_start = 0;
341 r_refdef.fog_end = 16384;
342 r_refdef.fog_height = 1<<30;
343 r_refdef.fog_fadedepth = 128;
344 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
347 static void R_BuildBlankTextures(void)
349 unsigned char data[4];
350 data[2] = 128; // normal X
351 data[1] = 128; // normal Y
352 data[0] = 255; // normal Z
353 data[3] = 128; // height
354 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
359 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
364 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
369 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
372 static void R_BuildNoTexture(void)
375 unsigned char pix[16][16][4];
376 // this makes a light grey/dark grey checkerboard texture
377 for (y = 0;y < 16;y++)
379 for (x = 0;x < 16;x++)
381 if ((y < 8) ^ (x < 8))
397 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
400 static void R_BuildWhiteCube(void)
402 unsigned char data[6*1*1*4];
403 memset(data, 255, sizeof(data));
404 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
407 static void R_BuildNormalizationCube(void)
411 vec_t s, t, intensity;
414 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
415 for (side = 0;side < 6;side++)
417 for (y = 0;y < NORMSIZE;y++)
419 for (x = 0;x < NORMSIZE;x++)
421 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
422 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
457 intensity = 127.0f / sqrt(DotProduct(v, v));
458 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
459 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
460 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
461 data[((side*64+y)*64+x)*4+3] = 255;
465 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
469 static void R_BuildFogTexture(void)
473 unsigned char data1[FOGWIDTH][4];
474 //unsigned char data2[FOGWIDTH][4];
477 r_refdef.fogmasktable_start = r_refdef.fog_start;
478 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
479 r_refdef.fogmasktable_range = r_refdef.fogrange;
480 r_refdef.fogmasktable_density = r_refdef.fog_density;
482 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
483 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
485 d = (x * r - r_refdef.fogmasktable_start);
486 if(developer_extra.integer)
487 Con_DPrintf("%f ", d);
489 if (r_fog_exp2.integer)
490 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
492 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
493 if(developer_extra.integer)
494 Con_DPrintf(" : %f ", alpha);
495 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
496 if(developer_extra.integer)
497 Con_DPrintf(" = %f\n", alpha);
498 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
501 for (x = 0;x < FOGWIDTH;x++)
503 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
508 //data2[x][0] = 255 - b;
509 //data2[x][1] = 255 - b;
510 //data2[x][2] = 255 - b;
513 if (r_texture_fogattenuation)
515 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
516 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
520 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
521 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
525 static void R_BuildFogHeightTexture(void)
527 unsigned char *inpixels;
535 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
536 if (r_refdef.fogheighttexturename[0])
537 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
540 r_refdef.fog_height_tablesize = 0;
541 if (r_texture_fogheighttexture)
542 R_FreeTexture(r_texture_fogheighttexture);
543 r_texture_fogheighttexture = NULL;
544 if (r_refdef.fog_height_table2d)
545 Mem_Free(r_refdef.fog_height_table2d);
546 r_refdef.fog_height_table2d = NULL;
547 if (r_refdef.fog_height_table1d)
548 Mem_Free(r_refdef.fog_height_table1d);
549 r_refdef.fog_height_table1d = NULL;
553 r_refdef.fog_height_tablesize = size;
554 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
555 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
556 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
558 // LordHavoc: now the magic - what is that table2d for? it is a cooked
559 // average fog color table accounting for every fog layer between a point
560 // and the camera. (Note: attenuation is handled separately!)
561 for (y = 0;y < size;y++)
563 for (x = 0;x < size;x++)
569 for (j = x;j <= y;j++)
571 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
577 for (j = x;j >= y;j--)
579 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
584 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
585 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
586 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
587 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
590 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
593 //=======================================================================================================================================================
595 static const char *builtinshaderstring =
596 #include "shader_glsl.h"
599 const char *builtinhlslshaderstring =
600 #include "shader_hlsl.h"
603 char *glslshaderstring = NULL;
604 char *hlslshaderstring = NULL;
606 //=======================================================================================================================================================
608 typedef struct shaderpermutationinfo_s
613 shaderpermutationinfo_t;
615 typedef struct shadermodeinfo_s
617 const char *vertexfilename;
618 const char *geometryfilename;
619 const char *fragmentfilename;
625 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
626 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
628 {"#define USEDIFFUSE\n", " diffuse"},
629 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
630 {"#define USEVIEWTINT\n", " viewtint"},
631 {"#define USECOLORMAPPING\n", " colormapping"},
632 {"#define USESATURATION\n", " saturation"},
633 {"#define USEFOGINSIDE\n", " foginside"},
634 {"#define USEFOGOUTSIDE\n", " fogoutside"},
635 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
636 {"#define USEGAMMARAMPS\n", " gammaramps"},
637 {"#define USECUBEFILTER\n", " cubefilter"},
638 {"#define USEGLOW\n", " glow"},
639 {"#define USEBLOOM\n", " bloom"},
640 {"#define USESPECULAR\n", " specular"},
641 {"#define USEPOSTPROCESSING\n", " postprocessing"},
642 {"#define USEREFLECTION\n", " reflection"},
643 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
644 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
645 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
646 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
647 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
648 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
649 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
650 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
651 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
652 {"#define USEALPHAKILL\n", " alphakill"},
653 {"#define USEREFLECTCUBE\n", " reflectcube"},
654 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
655 {"#define USEBOUNCEGRID\n", " bouncegrid"},
658 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
659 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
661 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
662 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
663 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
664 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
665 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
666 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
667 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
668 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
669 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
670 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
671 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
672 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
673 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
674 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
675 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
676 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
679 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
681 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
682 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
683 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
684 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
685 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
686 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
687 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
688 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
689 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
690 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
691 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
692 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
693 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
694 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
695 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
696 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
699 struct r_glsl_permutation_s;
700 typedef struct r_glsl_permutation_s
703 struct r_glsl_permutation_s *hashnext;
705 unsigned int permutation;
707 /// indicates if we have tried compiling this permutation already
709 /// 0 if compilation failed
711 // texture units assigned to each detected uniform
712 int tex_Texture_First;
713 int tex_Texture_Second;
714 int tex_Texture_GammaRamps;
715 int tex_Texture_Normal;
716 int tex_Texture_Color;
717 int tex_Texture_Gloss;
718 int tex_Texture_Glow;
719 int tex_Texture_SecondaryNormal;
720 int tex_Texture_SecondaryColor;
721 int tex_Texture_SecondaryGloss;
722 int tex_Texture_SecondaryGlow;
723 int tex_Texture_Pants;
724 int tex_Texture_Shirt;
725 int tex_Texture_FogHeightTexture;
726 int tex_Texture_FogMask;
727 int tex_Texture_Lightmap;
728 int tex_Texture_Deluxemap;
729 int tex_Texture_Attenuation;
730 int tex_Texture_Cube;
731 int tex_Texture_Refraction;
732 int tex_Texture_Reflection;
733 int tex_Texture_ShadowMap2D;
734 int tex_Texture_CubeProjection;
735 int tex_Texture_ScreenDepth;
736 int tex_Texture_ScreenNormalMap;
737 int tex_Texture_ScreenDiffuse;
738 int tex_Texture_ScreenSpecular;
739 int tex_Texture_ReflectMask;
740 int tex_Texture_ReflectCube;
741 int tex_Texture_BounceGrid;
742 /// locations of detected uniforms in program object, or -1 if not found
743 int loc_Texture_First;
744 int loc_Texture_Second;
745 int loc_Texture_GammaRamps;
746 int loc_Texture_Normal;
747 int loc_Texture_Color;
748 int loc_Texture_Gloss;
749 int loc_Texture_Glow;
750 int loc_Texture_SecondaryNormal;
751 int loc_Texture_SecondaryColor;
752 int loc_Texture_SecondaryGloss;
753 int loc_Texture_SecondaryGlow;
754 int loc_Texture_Pants;
755 int loc_Texture_Shirt;
756 int loc_Texture_FogHeightTexture;
757 int loc_Texture_FogMask;
758 int loc_Texture_Lightmap;
759 int loc_Texture_Deluxemap;
760 int loc_Texture_Attenuation;
761 int loc_Texture_Cube;
762 int loc_Texture_Refraction;
763 int loc_Texture_Reflection;
764 int loc_Texture_ShadowMap2D;
765 int loc_Texture_CubeProjection;
766 int loc_Texture_ScreenDepth;
767 int loc_Texture_ScreenNormalMap;
768 int loc_Texture_ScreenDiffuse;
769 int loc_Texture_ScreenSpecular;
770 int loc_Texture_ReflectMask;
771 int loc_Texture_ReflectCube;
772 int loc_Texture_BounceGrid;
774 int loc_BloomBlur_Parameters;
776 int loc_Color_Ambient;
777 int loc_Color_Diffuse;
778 int loc_Color_Specular;
782 int loc_DeferredColor_Ambient;
783 int loc_DeferredColor_Diffuse;
784 int loc_DeferredColor_Specular;
785 int loc_DeferredMod_Diffuse;
786 int loc_DeferredMod_Specular;
787 int loc_DistortScaleRefractReflect;
790 int loc_FogHeightFade;
792 int loc_FogPlaneViewDist;
793 int loc_FogRangeRecip;
796 int loc_LightPosition;
797 int loc_OffsetMapping_Scale;
799 int loc_ReflectColor;
800 int loc_ReflectFactor;
801 int loc_ReflectOffset;
802 int loc_RefractColor;
804 int loc_ScreenCenterRefractReflect;
805 int loc_ScreenScaleRefractReflect;
806 int loc_ScreenToDepth;
807 int loc_ShadowMap_Parameters;
808 int loc_ShadowMap_TextureScale;
809 int loc_SpecularPower;
814 int loc_ViewTintColor;
816 int loc_ModelToLight;
818 int loc_BackgroundTexMatrix;
819 int loc_ModelViewProjectionMatrix;
820 int loc_ModelViewMatrix;
821 int loc_PixelToScreenTexCoord;
822 int loc_ModelToReflectCube;
823 int loc_ShadowMapMatrix;
824 int loc_BloomColorSubtract;
825 int loc_NormalmapScrollBlend;
826 int loc_BounceGridMatrix;
827 int loc_BounceGridIntensity;
829 r_glsl_permutation_t;
831 #define SHADERPERMUTATION_HASHSIZE 256
834 // non-degradable "lightweight" shader parameters to keep the permutations simpler
835 // these can NOT degrade! only use for simple stuff
838 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
839 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
840 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
841 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
842 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
843 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5 ///< postprocess uservec4 is enabled
845 #define SHADERSTATICPARMS_COUNT 6
847 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
848 static int shaderstaticparms_count = 0;
850 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
851 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
852 qboolean R_CompileShader_CheckStaticParms(void)
854 static int r_compileshader_staticparms_save[1];
855 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
856 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
859 if (r_glsl_saturation_redcompensate.integer)
860 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
861 if (r_shadow_glossexact.integer)
862 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
863 if (r_glsl_postprocess.integer)
865 if (r_glsl_postprocess_uservec1_enable.integer)
866 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
867 if (r_glsl_postprocess_uservec2_enable.integer)
868 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
869 if (r_glsl_postprocess_uservec3_enable.integer)
870 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
871 if (r_glsl_postprocess_uservec4_enable.integer)
872 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
874 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
877 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
878 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
879 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
881 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
882 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
884 shaderstaticparms_count = 0;
887 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
888 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
889 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
890 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
891 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
892 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
895 /// information about each possible shader permutation
896 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
897 /// currently selected permutation
898 r_glsl_permutation_t *r_glsl_permutation;
899 /// storage for permutations linked in the hash table
900 memexpandablearray_t r_glsl_permutationarray;
902 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
904 //unsigned int hashdepth = 0;
905 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
906 r_glsl_permutation_t *p;
907 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
909 if (p->mode == mode && p->permutation == permutation)
911 //if (hashdepth > 10)
912 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
917 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
919 p->permutation = permutation;
920 p->hashnext = r_glsl_permutationhash[mode][hashindex];
921 r_glsl_permutationhash[mode][hashindex] = p;
922 //if (hashdepth > 10)
923 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
927 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
930 if (!filename || !filename[0])
932 if (!strcmp(filename, "glsl/default.glsl"))
934 if (!glslshaderstring)
936 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
937 if (glslshaderstring)
938 Con_DPrintf("Loading shaders from file %s...\n", filename);
940 glslshaderstring = (char *)builtinshaderstring;
942 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
943 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
946 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
949 if (printfromdisknotice)
950 Con_DPrintf("from disk %s... ", filename);
956 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
960 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
961 char *vertexstring, *geometrystring, *fragmentstring;
962 char permutationname[256];
963 int vertstrings_count = 0;
964 int geomstrings_count = 0;
965 int fragstrings_count = 0;
966 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
967 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
968 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
975 permutationname[0] = 0;
976 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
977 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
978 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
980 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
982 // the first pretext is which type of shader to compile as
983 // (later these will all be bound together as a program object)
984 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
985 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
986 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
988 // the second pretext is the mode (for example a light source)
989 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
990 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
991 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
992 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
994 // now add all the permutation pretexts
995 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
997 if (permutation & (1<<i))
999 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1000 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1001 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1002 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1006 // keep line numbers correct
1007 vertstrings_list[vertstrings_count++] = "\n";
1008 geomstrings_list[geomstrings_count++] = "\n";
1009 fragstrings_list[fragstrings_count++] = "\n";
1014 R_CompileShader_AddStaticParms(mode, permutation);
1015 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1016 vertstrings_count += shaderstaticparms_count;
1017 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1018 geomstrings_count += shaderstaticparms_count;
1019 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1020 fragstrings_count += shaderstaticparms_count;
1022 // now append the shader text itself
1023 vertstrings_list[vertstrings_count++] = vertexstring;
1024 geomstrings_list[geomstrings_count++] = geometrystring;
1025 fragstrings_list[fragstrings_count++] = fragmentstring;
1027 // if any sources were NULL, clear the respective list
1029 vertstrings_count = 0;
1030 if (!geometrystring)
1031 geomstrings_count = 0;
1032 if (!fragmentstring)
1033 fragstrings_count = 0;
1035 // compile the shader program
1036 if (vertstrings_count + geomstrings_count + fragstrings_count)
1037 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1041 qglUseProgram(p->program);CHECKGLERROR
1042 // look up all the uniform variable names we care about, so we don't
1043 // have to look them up every time we set them
1045 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1046 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1047 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1048 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1049 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1050 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1051 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1052 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1053 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1054 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1055 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1056 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1057 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1058 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1059 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1060 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1061 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1062 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1063 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1064 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1065 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1066 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1067 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1068 p->loc_Texture_ScreenDepth = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1069 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1070 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1071 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1072 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1073 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1074 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1075 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1076 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1077 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1078 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1079 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1080 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1081 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1082 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1083 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1084 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1085 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1086 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1087 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1088 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1089 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1090 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1091 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1092 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1093 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1094 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1095 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1096 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1097 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1098 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1099 p->loc_OffsetMapping_Scale = qglGetUniformLocation(p->program, "OffsetMapping_Scale");
1100 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1101 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1102 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1103 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1104 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1105 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1106 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1107 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1108 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1109 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1110 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1111 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1112 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1113 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1114 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1115 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1116 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1117 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1118 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1119 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1120 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1121 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1122 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1123 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1124 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1125 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1126 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1127 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1128 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1129 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1130 // initialize the samplers to refer to the texture units we use
1131 p->tex_Texture_First = -1;
1132 p->tex_Texture_Second = -1;
1133 p->tex_Texture_GammaRamps = -1;
1134 p->tex_Texture_Normal = -1;
1135 p->tex_Texture_Color = -1;
1136 p->tex_Texture_Gloss = -1;
1137 p->tex_Texture_Glow = -1;
1138 p->tex_Texture_SecondaryNormal = -1;
1139 p->tex_Texture_SecondaryColor = -1;
1140 p->tex_Texture_SecondaryGloss = -1;
1141 p->tex_Texture_SecondaryGlow = -1;
1142 p->tex_Texture_Pants = -1;
1143 p->tex_Texture_Shirt = -1;
1144 p->tex_Texture_FogHeightTexture = -1;
1145 p->tex_Texture_FogMask = -1;
1146 p->tex_Texture_Lightmap = -1;
1147 p->tex_Texture_Deluxemap = -1;
1148 p->tex_Texture_Attenuation = -1;
1149 p->tex_Texture_Cube = -1;
1150 p->tex_Texture_Refraction = -1;
1151 p->tex_Texture_Reflection = -1;
1152 p->tex_Texture_ShadowMap2D = -1;
1153 p->tex_Texture_CubeProjection = -1;
1154 p->tex_Texture_ScreenDepth = -1;
1155 p->tex_Texture_ScreenNormalMap = -1;
1156 p->tex_Texture_ScreenDiffuse = -1;
1157 p->tex_Texture_ScreenSpecular = -1;
1158 p->tex_Texture_ReflectMask = -1;
1159 p->tex_Texture_ReflectCube = -1;
1160 p->tex_Texture_BounceGrid = -1;
1162 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1163 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1164 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1165 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1166 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1167 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1168 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1169 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1170 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1171 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1172 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1173 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1174 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1175 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1176 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1177 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1178 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1179 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1180 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1181 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1182 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1183 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1184 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1185 if (p->loc_Texture_ScreenDepth >= 0) {p->tex_Texture_ScreenDepth = sampler;qglUniform1i(p->loc_Texture_ScreenDepth , sampler);sampler++;}
1186 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1187 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1188 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1189 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1190 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1191 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1193 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1196 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1200 Mem_Free(vertexstring);
1202 Mem_Free(geometrystring);
1204 Mem_Free(fragmentstring);
1207 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1209 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1210 if (r_glsl_permutation != perm)
1212 r_glsl_permutation = perm;
1213 if (!r_glsl_permutation->program)
1215 if (!r_glsl_permutation->compiled)
1216 R_GLSL_CompilePermutation(perm, mode, permutation);
1217 if (!r_glsl_permutation->program)
1219 // remove features until we find a valid permutation
1221 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1223 // reduce i more quickly whenever it would not remove any bits
1224 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1225 if (!(permutation & j))
1228 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1229 if (!r_glsl_permutation->compiled)
1230 R_GLSL_CompilePermutation(perm, mode, permutation);
1231 if (r_glsl_permutation->program)
1234 if (i >= SHADERPERMUTATION_COUNT)
1236 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1237 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1238 qglUseProgram(0);CHECKGLERROR
1239 return; // no bit left to clear, entire mode is broken
1244 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1246 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1247 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1248 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1255 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1256 extern D3DCAPS9 vid_d3d9caps;
1259 struct r_hlsl_permutation_s;
1260 typedef struct r_hlsl_permutation_s
1262 /// hash lookup data
1263 struct r_hlsl_permutation_s *hashnext;
1265 unsigned int permutation;
1267 /// indicates if we have tried compiling this permutation already
1269 /// NULL if compilation failed
1270 IDirect3DVertexShader9 *vertexshader;
1271 IDirect3DPixelShader9 *pixelshader;
1273 r_hlsl_permutation_t;
1275 typedef enum D3DVSREGISTER_e
1277 D3DVSREGISTER_TexMatrix = 0, // float4x4
1278 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1279 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1280 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1281 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1282 D3DVSREGISTER_ModelToLight = 20, // float4x4
1283 D3DVSREGISTER_EyePosition = 24,
1284 D3DVSREGISTER_FogPlane = 25,
1285 D3DVSREGISTER_LightDir = 26,
1286 D3DVSREGISTER_LightPosition = 27,
1290 typedef enum D3DPSREGISTER_e
1292 D3DPSREGISTER_Alpha = 0,
1293 D3DPSREGISTER_BloomBlur_Parameters = 1,
1294 D3DPSREGISTER_ClientTime = 2,
1295 D3DPSREGISTER_Color_Ambient = 3,
1296 D3DPSREGISTER_Color_Diffuse = 4,
1297 D3DPSREGISTER_Color_Specular = 5,
1298 D3DPSREGISTER_Color_Glow = 6,
1299 D3DPSREGISTER_Color_Pants = 7,
1300 D3DPSREGISTER_Color_Shirt = 8,
1301 D3DPSREGISTER_DeferredColor_Ambient = 9,
1302 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1303 D3DPSREGISTER_DeferredColor_Specular = 11,
1304 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1305 D3DPSREGISTER_DeferredMod_Specular = 13,
1306 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1307 D3DPSREGISTER_EyePosition = 15, // unused
1308 D3DPSREGISTER_FogColor = 16,
1309 D3DPSREGISTER_FogHeightFade = 17,
1310 D3DPSREGISTER_FogPlane = 18,
1311 D3DPSREGISTER_FogPlaneViewDist = 19,
1312 D3DPSREGISTER_FogRangeRecip = 20,
1313 D3DPSREGISTER_LightColor = 21,
1314 D3DPSREGISTER_LightDir = 22, // unused
1315 D3DPSREGISTER_LightPosition = 23,
1316 D3DPSREGISTER_OffsetMapping_Scale = 24,
1317 D3DPSREGISTER_PixelSize = 25,
1318 D3DPSREGISTER_ReflectColor = 26,
1319 D3DPSREGISTER_ReflectFactor = 27,
1320 D3DPSREGISTER_ReflectOffset = 28,
1321 D3DPSREGISTER_RefractColor = 29,
1322 D3DPSREGISTER_Saturation = 30,
1323 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1324 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1325 D3DPSREGISTER_ScreenToDepth = 33,
1326 D3DPSREGISTER_ShadowMap_Parameters = 34,
1327 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1328 D3DPSREGISTER_SpecularPower = 36,
1329 D3DPSREGISTER_UserVec1 = 37,
1330 D3DPSREGISTER_UserVec2 = 38,
1331 D3DPSREGISTER_UserVec3 = 39,
1332 D3DPSREGISTER_UserVec4 = 40,
1333 D3DPSREGISTER_ViewTintColor = 41,
1334 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1335 D3DPSREGISTER_BloomColorSubtract = 43,
1336 D3DPSREGISTER_ViewToLight = 44, // float4x4
1337 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1338 D3DPSREGISTER_NormalmapScrollBlend = 52,
1343 /// information about each possible shader permutation
1344 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1345 /// currently selected permutation
1346 r_hlsl_permutation_t *r_hlsl_permutation;
1347 /// storage for permutations linked in the hash table
1348 memexpandablearray_t r_hlsl_permutationarray;
1350 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1352 //unsigned int hashdepth = 0;
1353 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1354 r_hlsl_permutation_t *p;
1355 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1357 if (p->mode == mode && p->permutation == permutation)
1359 //if (hashdepth > 10)
1360 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1365 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1367 p->permutation = permutation;
1368 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1369 r_hlsl_permutationhash[mode][hashindex] = p;
1370 //if (hashdepth > 10)
1371 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1375 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1378 if (!filename || !filename[0])
1380 if (!strcmp(filename, "hlsl/default.hlsl"))
1382 if (!hlslshaderstring)
1384 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1385 if (hlslshaderstring)
1386 Con_DPrintf("Loading shaders from file %s...\n", filename);
1388 hlslshaderstring = (char *)builtinhlslshaderstring;
1390 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1391 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1392 return shaderstring;
1394 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1397 if (printfromdisknotice)
1398 Con_DPrintf("from disk %s... ", filename);
1399 return shaderstring;
1401 return shaderstring;
1405 //#include <d3dx9shader.h>
1406 //#include <d3dx9mesh.h>
1408 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1410 DWORD *vsbin = NULL;
1411 DWORD *psbin = NULL;
1412 fs_offset_t vsbinsize;
1413 fs_offset_t psbinsize;
1414 // IDirect3DVertexShader9 *vs = NULL;
1415 // IDirect3DPixelShader9 *ps = NULL;
1416 ID3DXBuffer *vslog = NULL;
1417 ID3DXBuffer *vsbuffer = NULL;
1418 ID3DXConstantTable *vsconstanttable = NULL;
1419 ID3DXBuffer *pslog = NULL;
1420 ID3DXBuffer *psbuffer = NULL;
1421 ID3DXConstantTable *psconstanttable = NULL;
1424 char temp[MAX_INPUTLINE];
1425 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1426 qboolean debugshader = gl_paranoid.integer != 0;
1427 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1428 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1431 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1432 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1434 if ((!vsbin && vertstring) || (!psbin && fragstring))
1436 const char* dllnames_d3dx9 [] =
1460 dllhandle_t d3dx9_dll = NULL;
1461 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1462 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1463 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1464 dllfunction_t d3dx9_dllfuncs[] =
1466 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1467 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1468 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1471 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1473 DWORD shaderflags = 0;
1475 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1476 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1477 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1478 if (vertstring && vertstring[0])
1482 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1483 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1484 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1485 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1488 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1491 vsbinsize = vsbuffer->GetBufferSize();
1492 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1493 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1494 vsbuffer->Release();
1498 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1499 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1503 if (fragstring && fragstring[0])
1507 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1508 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1509 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1510 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1513 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1516 psbinsize = psbuffer->GetBufferSize();
1517 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1518 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1519 psbuffer->Release();
1523 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1524 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1528 Sys_UnloadLibrary(&d3dx9_dll);
1531 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1535 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1536 if (FAILED(vsresult))
1537 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1538 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1539 if (FAILED(psresult))
1540 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1542 // free the shader data
1543 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1544 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1547 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1550 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1551 int vertstring_length = 0;
1552 int geomstring_length = 0;
1553 int fragstring_length = 0;
1555 char *vertexstring, *geometrystring, *fragmentstring;
1556 char *vertstring, *geomstring, *fragstring;
1557 char permutationname[256];
1558 char cachename[256];
1559 int vertstrings_count = 0;
1560 int geomstrings_count = 0;
1561 int fragstrings_count = 0;
1562 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1563 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1564 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1569 p->vertexshader = NULL;
1570 p->pixelshader = NULL;
1572 permutationname[0] = 0;
1574 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
1575 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1576 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1578 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1579 strlcat(cachename, "hlsl/", sizeof(cachename));
1581 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1582 vertstrings_count = 0;
1583 geomstrings_count = 0;
1584 fragstrings_count = 0;
1585 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1586 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1587 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1589 // the first pretext is which type of shader to compile as
1590 // (later these will all be bound together as a program object)
1591 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1592 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1593 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1595 // the second pretext is the mode (for example a light source)
1596 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1597 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1598 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1599 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1600 strlcat(cachename, modeinfo->name, sizeof(cachename));
1602 // now add all the permutation pretexts
1603 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1605 if (permutation & (1<<i))
1607 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1608 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1609 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1610 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1611 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1615 // keep line numbers correct
1616 vertstrings_list[vertstrings_count++] = "\n";
1617 geomstrings_list[geomstrings_count++] = "\n";
1618 fragstrings_list[fragstrings_count++] = "\n";
1623 R_CompileShader_AddStaticParms(mode, permutation);
1624 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1625 vertstrings_count += shaderstaticparms_count;
1626 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1627 geomstrings_count += shaderstaticparms_count;
1628 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1629 fragstrings_count += shaderstaticparms_count;
1631 // replace spaces in the cachename with _ characters
1632 for (i = 0;cachename[i];i++)
1633 if (cachename[i] == ' ')
1636 // now append the shader text itself
1637 vertstrings_list[vertstrings_count++] = vertexstring;
1638 geomstrings_list[geomstrings_count++] = geometrystring;
1639 fragstrings_list[fragstrings_count++] = fragmentstring;
1641 // if any sources were NULL, clear the respective list
1643 vertstrings_count = 0;
1644 if (!geometrystring)
1645 geomstrings_count = 0;
1646 if (!fragmentstring)
1647 fragstrings_count = 0;
1649 vertstring_length = 0;
1650 for (i = 0;i < vertstrings_count;i++)
1651 vertstring_length += strlen(vertstrings_list[i]);
1652 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1653 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1654 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1656 geomstring_length = 0;
1657 for (i = 0;i < geomstrings_count;i++)
1658 geomstring_length += strlen(geomstrings_list[i]);
1659 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1660 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1661 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1663 fragstring_length = 0;
1664 for (i = 0;i < fragstrings_count;i++)
1665 fragstring_length += strlen(fragstrings_list[i]);
1666 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1667 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1668 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1670 // try to load the cached shader, or generate one
1671 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1673 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1674 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1676 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1680 Mem_Free(vertstring);
1682 Mem_Free(geomstring);
1684 Mem_Free(fragstring);
1686 Mem_Free(vertexstring);
1688 Mem_Free(geometrystring);
1690 Mem_Free(fragmentstring);
1693 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1694 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1695 static inline void hlslVSSetParameter4f(D3DVSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1696 static inline void hlslVSSetParameter3f(D3DVSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1697 static inline void hlslVSSetParameter2f(D3DVSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1698 static inline void hlslVSSetParameter1f(D3DVSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1700 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1701 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1702 static inline void hlslPSSetParameter4f(D3DPSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1703 static inline void hlslPSSetParameter3f(D3DPSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1704 static inline void hlslPSSetParameter2f(D3DPSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1705 static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1707 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1709 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1710 if (r_hlsl_permutation != perm)
1712 r_hlsl_permutation = perm;
1713 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1715 if (!r_hlsl_permutation->compiled)
1716 R_HLSL_CompilePermutation(perm, mode, permutation);
1717 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1719 // remove features until we find a valid permutation
1721 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1723 // reduce i more quickly whenever it would not remove any bits
1724 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1725 if (!(permutation & j))
1728 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1729 if (!r_hlsl_permutation->compiled)
1730 R_HLSL_CompilePermutation(perm, mode, permutation);
1731 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1734 if (i >= SHADERPERMUTATION_COUNT)
1736 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1737 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1738 return; // no bit left to clear, entire mode is broken
1742 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1743 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1745 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1746 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1747 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1751 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1753 DPSOFTRAST_SetShader(mode, permutation);
1754 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1755 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1756 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1759 void R_GLSL_Restart_f(void)
1761 unsigned int i, limit;
1762 if (glslshaderstring && glslshaderstring != builtinshaderstring)
1763 Mem_Free(glslshaderstring);
1764 glslshaderstring = NULL;
1765 if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1766 Mem_Free(hlslshaderstring);
1767 hlslshaderstring = NULL;
1768 switch(vid.renderpath)
1770 case RENDERPATH_D3D9:
1773 r_hlsl_permutation_t *p;
1774 r_hlsl_permutation = NULL;
1775 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1776 for (i = 0;i < limit;i++)
1778 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1780 if (p->vertexshader)
1781 IDirect3DVertexShader9_Release(p->vertexshader);
1783 IDirect3DPixelShader9_Release(p->pixelshader);
1784 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1787 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1791 case RENDERPATH_D3D10:
1792 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1794 case RENDERPATH_D3D11:
1795 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1797 case RENDERPATH_GL20:
1798 case RENDERPATH_GLES2:
1800 r_glsl_permutation_t *p;
1801 r_glsl_permutation = NULL;
1802 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1803 for (i = 0;i < limit;i++)
1805 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1807 GL_Backend_FreeProgram(p->program);
1808 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1811 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1814 case RENDERPATH_GL13:
1815 case RENDERPATH_GL11:
1817 case RENDERPATH_SOFT:
1822 void R_GLSL_DumpShader_f(void)
1827 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1830 FS_Print(file, "/* The engine may define the following macros:\n");
1831 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1832 for (i = 0;i < SHADERMODE_COUNT;i++)
1833 FS_Print(file, glslshadermodeinfo[i].pretext);
1834 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1835 FS_Print(file, shaderpermutationinfo[i].pretext);
1836 FS_Print(file, "*/\n");
1837 FS_Print(file, builtinshaderstring);
1839 Con_Printf("glsl/default.glsl written\n");
1842 Con_Printf("failed to write to glsl/default.glsl\n");
1844 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1847 FS_Print(file, "/* The engine may define the following macros:\n");
1848 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1849 for (i = 0;i < SHADERMODE_COUNT;i++)
1850 FS_Print(file, hlslshadermodeinfo[i].pretext);
1851 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1852 FS_Print(file, shaderpermutationinfo[i].pretext);
1853 FS_Print(file, "*/\n");
1854 FS_Print(file, builtinhlslshaderstring);
1856 Con_Printf("hlsl/default.hlsl written\n");
1859 Con_Printf("failed to write to hlsl/default.hlsl\n");
1862 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1865 texturemode = GL_MODULATE;
1866 switch (vid.renderpath)
1868 case RENDERPATH_D3D9:
1870 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1871 R_Mesh_TexBind(GL20TU_FIRST , first );
1872 R_Mesh_TexBind(GL20TU_SECOND, second);
1875 case RENDERPATH_D3D10:
1876 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1878 case RENDERPATH_D3D11:
1879 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1881 case RENDERPATH_GL20:
1882 case RENDERPATH_GLES2:
1883 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1884 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1885 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1887 case RENDERPATH_GL13:
1888 R_Mesh_TexBind(0, first );
1889 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1890 R_Mesh_TexBind(1, second);
1892 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1894 case RENDERPATH_GL11:
1895 R_Mesh_TexBind(0, first );
1897 case RENDERPATH_SOFT:
1898 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1899 R_Mesh_TexBind(GL20TU_FIRST , first );
1900 R_Mesh_TexBind(GL20TU_SECOND, second);
1905 void R_SetupShader_DepthOrShadow(void)
1907 switch (vid.renderpath)
1909 case RENDERPATH_D3D9:
1911 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1914 case RENDERPATH_D3D10:
1915 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1917 case RENDERPATH_D3D11:
1918 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1920 case RENDERPATH_GL20:
1921 case RENDERPATH_GLES2:
1922 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1924 case RENDERPATH_GL13:
1925 R_Mesh_TexBind(0, 0);
1926 R_Mesh_TexBind(1, 0);
1928 case RENDERPATH_GL11:
1929 R_Mesh_TexBind(0, 0);
1931 case RENDERPATH_SOFT:
1932 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1937 void R_SetupShader_ShowDepth(void)
1939 switch (vid.renderpath)
1941 case RENDERPATH_D3D9:
1943 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1946 case RENDERPATH_D3D10:
1947 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1949 case RENDERPATH_D3D11:
1950 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1952 case RENDERPATH_GL20:
1953 case RENDERPATH_GLES2:
1954 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1956 case RENDERPATH_GL13:
1958 case RENDERPATH_GL11:
1960 case RENDERPATH_SOFT:
1961 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
1966 extern qboolean r_shadow_usingdeferredprepass;
1967 extern cvar_t r_shadow_deferred_8bitrange;
1968 extern rtexture_t *r_shadow_attenuationgradienttexture;
1969 extern rtexture_t *r_shadow_attenuation2dtexture;
1970 extern rtexture_t *r_shadow_attenuation3dtexture;
1971 extern qboolean r_shadow_usingshadowmap2d;
1972 extern qboolean r_shadow_usingshadowmaportho;
1973 extern float r_shadow_shadowmap_texturescale[2];
1974 extern float r_shadow_shadowmap_parameters[4];
1975 extern qboolean r_shadow_shadowmapvsdct;
1976 extern qboolean r_shadow_shadowmapsampler;
1977 extern int r_shadow_shadowmappcf;
1978 extern rtexture_t *r_shadow_shadowmap2dtexture;
1979 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
1980 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
1981 extern matrix4x4_t r_shadow_shadowmapmatrix;
1982 extern int r_shadow_shadowmaplod; // changes for each light based on distance
1983 extern int r_shadow_prepass_width;
1984 extern int r_shadow_prepass_height;
1985 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
1986 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
1987 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
1988 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
1989 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
1990 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
1992 // a blendfunc allows colormod if:
1993 // a) it can never keep the destination pixel invariant, or
1994 // b) it can keep the destination pixel invariant, and still can do so if colormodded
1995 // this is to prevent unintended side effects from colormod
1998 // IF there is a (s, sa) for which for all (d, da),
1999 // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
2000 // THEN, for this (s, sa) and all (colormod, d, da):
2001 // s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
2002 // OBVIOUSLY, this means that
2003 // s*colormod * src(s*colormod, d, sa, da) = 0
2004 // dst(s*colormod, d, sa, da) = 1
2006 // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
2008 // main condition to leave dst color invariant:
2009 // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
2011 // s * 0 + d * dst(s, d, sa, da) == d
2012 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2013 // => colormod is a problem for GL_SRC_COLOR only
2015 // s + d * dst(s, d, sa, da) == d
2017 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2018 // => colormod is never problematic for these
2019 // src == GL_SRC_COLOR:
2020 // s*s + d * dst(s, d, sa, da) == d
2022 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2023 // => colormod is never problematic for these
2024 // src == GL_ONE_MINUS_SRC_COLOR:
2025 // s*(1-s) + d * dst(s, d, sa, da) == d
2026 // => s == 0 or s == 1
2027 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2028 // => colormod is a problem for GL_SRC_COLOR only
2029 // src == GL_DST_COLOR
2030 // s*d + d * dst(s, d, sa, da) == d
2032 // => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2033 // => colormod is always a problem
2036 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2037 // => colormod is never problematic for these
2038 // => BUT, we do not know s! We must assume it is problematic
2039 // then... except in GL_ONE case, where we know all invariant
2041 // src == GL_ONE_MINUS_DST_COLOR
2042 // s*(1-d) + d * dst(s, d, sa, da) == d
2043 // => s == 0 (1-d is impossible to handle for our desired result)
2044 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2045 // => colormod is never problematic for these
2046 // src == GL_SRC_ALPHA
2047 // s*sa + d * dst(s, d, sa, da) == d
2048 // => s == 0, or sa == 0
2049 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2050 // => colormod breaks in the case GL_SRC_COLOR only
2051 // src == GL_ONE_MINUS_SRC_ALPHA
2052 // s*(1-sa) + d * dst(s, d, sa, da) == d
2053 // => s == 0, or sa == 1
2054 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2055 // => colormod breaks in the case GL_SRC_COLOR only
2056 // src == GL_DST_ALPHA
2057 // s*da + d * dst(s, d, sa, da) == d
2059 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2060 // => colormod is never problematic for these
2065 case GL_ONE_MINUS_SRC_COLOR:
2067 case GL_ONE_MINUS_SRC_ALPHA:
2068 if(dst == GL_SRC_COLOR)
2073 case GL_ONE_MINUS_DST_COLOR:
2075 case GL_ONE_MINUS_DST_ALPHA:
2085 static qboolean R_BlendFuncAllowsFog(int src, int dst)
2087 // a blendfunc allows fog if:
2088 // a) it can never keep the destination pixel invariant, or
2089 // b) it can keep the destination pixel invariant, and still can do so if fogged
2090 // this is to prevent unintended side effects from colormod
2092 // main condition to leave dst color invariant:
2093 // s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
2095 // s * 0 + d * dst(s, d, sa, da) == d
2096 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2097 // => fog is a problem for GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR only
2099 // s + d * dst(s, d, sa, da) == d
2101 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2102 // => fog is a problem for all of them, because we require s == 0
2103 // src == GL_SRC_COLOR:
2104 // s*s + d * dst(s, d, sa, da) == d
2106 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2107 // => fog is a problem for all of them, because we require s == 0
2108 // src == GL_ONE_MINUS_SRC_COLOR:
2109 // s*(1-s) + d * dst(s, d, sa, da) == d
2110 // => s == 0 or s == 1
2111 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2112 // => fog is a problem for all of them, because we require s == 0 or s == 1
2113 // src == GL_DST_COLOR
2114 // s*d + d * dst(s, d, sa, da) == d
2116 // => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2117 // => fog is a problem for all of them, because we require s == 1
2120 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2121 // => colormod is never problematic for these
2122 // => BUT, we do not know s! We must assume it is problematic
2123 // then... except in GL_ONE case, where we know all invariant
2125 // => fog is a problem for all of them, because we require s == 0 or s == 1
2126 // src == GL_ONE_MINUS_DST_COLOR
2127 // s*(1-d) + d * dst(s, d, sa, da) == d
2128 // => s == 0 (1-d is impossible to handle for our desired result)
2129 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2130 // => colormod is never problematic for these
2131 // => fog is a problem for all of them, because we require s == 0
2132 // src == GL_SRC_ALPHA
2133 // s*sa + d * dst(s, d, sa, da) == d
2134 // => s == 0, or sa == 0
2135 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2136 // => fog breaks in the case GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR only
2137 // src == GL_ONE_MINUS_SRC_ALPHA
2138 // s*(1-sa) + d * dst(s, d, sa, da) == d
2139 // => s == 0, or sa == 1
2140 // => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2141 // => colormod breaks in the case GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR only
2142 // src == GL_DST_ALPHA
2143 // s*da + d * dst(s, d, sa, da) == d
2145 // => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
2146 // => fog is a problem for all of them, because we require s == 0
2152 case GL_ONE_MINUS_SRC_ALPHA:
2153 if(dst == GL_SRC_COLOR || dst == GL_ONE_MINUS_SRC_COLOR)
2156 case GL_ONE_MINUS_SRC_COLOR:
2157 case GL_ONE_MINUS_DST_COLOR:
2158 if(dst == GL_ONE || dst == GL_SRC_COLOR || dst == GL_ONE_MINUS_SRC_COLOR || dst == GL_SRC_ALPHA || dst == GL_ONE_MINUS_SRC_ALPHA)
2164 if(dst == GL_ONE || dst == GL_ONE_MINUS_SRC_COLOR || dst == GL_SRC_ALPHA || dst == GL_ONE_MINUS_SRC_ALPHA)
2168 if(dst == GL_ZERO || dst == GL_ONE_MINUS_SRC_COLOR || dst == GL_SRC_ALPHA || dst == GL_ONE_MINUS_SRC_ALPHA)
2171 case GL_ONE_MINUS_DST_ALPHA:
2177 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)
2179 // select a permutation of the lighting shader appropriate to this
2180 // combination of texture, entity, light source, and fogging, only use the
2181 // minimum features necessary to avoid wasting rendering time in the
2182 // fragment shader on features that are not being used
2183 unsigned int permutation = 0;
2184 unsigned int mode = 0;
2185 qboolean allow_colormod;
2187 static float dummy_colormod[3] = {1, 1, 1};
2188 float *colormod = rsurface.colormod;
2190 matrix4x4_t tempmatrix;
2191 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2192 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2193 permutation |= SHADERPERMUTATION_ALPHAKILL;
2194 if (rsurfacepass == RSURFPASS_BACKGROUND)
2196 // distorted background
2197 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2199 mode = SHADERMODE_WATER;
2200 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2201 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
2202 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2204 // this is the right thing to do for wateralpha
2205 GL_BlendFunc(GL_ONE, GL_ZERO);
2206 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
2207 allow_fog = R_BlendFuncAllowsFog(GL_ONE, GL_ZERO);
2211 // this is the right thing to do for entity alpha
2212 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2213 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2214 allow_fog = R_BlendFuncAllowsFog(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2217 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2219 mode = SHADERMODE_REFRACTION;
2220 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2221 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2222 allow_fog = R_BlendFuncAllowsFog(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2226 mode = SHADERMODE_GENERIC;
2227 permutation |= SHADERPERMUTATION_DIFFUSE;
2228 GL_BlendFunc(GL_ONE, GL_ZERO);
2229 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
2230 allow_fog = R_BlendFuncAllowsFog(GL_ONE, GL_ZERO);
2233 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2235 if (r_glsl_offsetmapping.integer)
2237 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2238 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2239 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2240 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2241 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2243 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2244 if (r_glsl_offsetmapping_reliefmapping.integer)
2245 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2248 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2249 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2250 // normalmap (deferred prepass), may use alpha test on diffuse
2251 mode = SHADERMODE_DEFERREDGEOMETRY;
2252 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2253 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2254 GL_BlendFunc(GL_ONE, GL_ZERO);
2255 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
2256 allow_fog = R_BlendFuncAllowsFog(GL_ONE, GL_ZERO);
2258 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2260 if (r_glsl_offsetmapping.integer)
2262 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2263 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2264 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2265 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2266 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2268 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2269 if (r_glsl_offsetmapping_reliefmapping.integer)
2270 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2273 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2274 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2276 mode = SHADERMODE_LIGHTSOURCE;
2277 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2278 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2279 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2280 permutation |= SHADERPERMUTATION_CUBEFILTER;
2281 if (diffusescale > 0)
2282 permutation |= SHADERPERMUTATION_DIFFUSE;
2283 if (specularscale > 0)
2284 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2285 if (r_refdef.fogenabled)
2286 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2287 if (rsurface.texture->colormapping)
2288 permutation |= SHADERPERMUTATION_COLORMAPPING;
2289 if (r_shadow_usingshadowmap2d)
2291 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2292 if(r_shadow_shadowmapvsdct)
2293 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2295 if (r_shadow_shadowmapsampler)
2296 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2297 if (r_shadow_shadowmappcf > 1)
2298 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2299 else if (r_shadow_shadowmappcf)
2300 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2302 if (rsurface.texture->reflectmasktexture)
2303 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2304 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2305 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
2306 allow_fog = R_BlendFuncAllowsFog(GL_SRC_ALPHA, GL_ONE);
2308 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2310 if (r_glsl_offsetmapping.integer)
2312 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2313 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2314 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2315 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2316 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2318 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2319 if (r_glsl_offsetmapping_reliefmapping.integer)
2320 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2323 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2324 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2325 // unshaded geometry (fullbright or ambient model lighting)
2326 mode = SHADERMODE_FLATCOLOR;
2327 ambientscale = diffusescale = specularscale = 0;
2328 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2329 permutation |= SHADERPERMUTATION_GLOW;
2330 if (r_refdef.fogenabled)
2331 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2332 if (rsurface.texture->colormapping)
2333 permutation |= SHADERPERMUTATION_COLORMAPPING;
2334 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2336 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2337 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2339 if (r_shadow_shadowmapsampler)
2340 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2341 if (r_shadow_shadowmappcf > 1)
2342 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2343 else if (r_shadow_shadowmappcf)
2344 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2346 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2347 permutation |= SHADERPERMUTATION_REFLECTION;
2348 if (rsurface.texture->reflectmasktexture)
2349 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2350 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2351 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2352 allow_fog = R_BlendFuncAllowsFog(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2354 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2356 if (r_glsl_offsetmapping.integer)
2358 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2359 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2360 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2361 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2362 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2364 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2365 if (r_glsl_offsetmapping_reliefmapping.integer)
2366 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2369 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2370 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2371 // directional model lighting
2372 mode = SHADERMODE_LIGHTDIRECTION;
2373 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2374 permutation |= SHADERPERMUTATION_GLOW;
2375 permutation |= SHADERPERMUTATION_DIFFUSE;
2376 if (specularscale > 0)
2377 permutation |= SHADERPERMUTATION_SPECULAR;
2378 if (r_refdef.fogenabled)
2379 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2380 if (rsurface.texture->colormapping)
2381 permutation |= SHADERPERMUTATION_COLORMAPPING;
2382 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2384 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2385 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2387 if (r_shadow_shadowmapsampler)
2388 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2389 if (r_shadow_shadowmappcf > 1)
2390 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2391 else if (r_shadow_shadowmappcf)
2392 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2394 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2395 permutation |= SHADERPERMUTATION_REFLECTION;
2396 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2397 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2398 if (rsurface.texture->reflectmasktexture)
2399 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2400 if (r_shadow_bouncegridtexture)
2401 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2402 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2403 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2404 allow_fog = R_BlendFuncAllowsFog(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2406 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2408 if (r_glsl_offsetmapping.integer)
2410 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2411 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2412 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2413 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2414 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2416 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2417 if (r_glsl_offsetmapping_reliefmapping.integer)
2418 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2421 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2422 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2423 // ambient model lighting
2424 mode = SHADERMODE_LIGHTDIRECTION;
2425 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2426 permutation |= SHADERPERMUTATION_GLOW;
2427 if (r_refdef.fogenabled)
2428 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2429 if (rsurface.texture->colormapping)
2430 permutation |= SHADERPERMUTATION_COLORMAPPING;
2431 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2433 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2434 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2436 if (r_shadow_shadowmapsampler)
2437 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2438 if (r_shadow_shadowmappcf > 1)
2439 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2440 else if (r_shadow_shadowmappcf)
2441 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2443 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2444 permutation |= SHADERPERMUTATION_REFLECTION;
2445 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2446 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2447 if (rsurface.texture->reflectmasktexture)
2448 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2449 if (r_shadow_bouncegridtexture)
2450 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2451 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2452 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2453 allow_fog = R_BlendFuncAllowsFog(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2457 if (r_glsl_offsetmapping.integer)
2459 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2460 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2461 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2462 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2463 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2465 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2466 if (r_glsl_offsetmapping_reliefmapping.integer)
2467 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2470 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2471 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2473 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2474 permutation |= SHADERPERMUTATION_GLOW;
2475 if (r_refdef.fogenabled)
2476 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2477 if (rsurface.texture->colormapping)
2478 permutation |= SHADERPERMUTATION_COLORMAPPING;
2479 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2481 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2482 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2484 if (r_shadow_shadowmapsampler)
2485 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2486 if (r_shadow_shadowmappcf > 1)
2487 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2488 else if (r_shadow_shadowmappcf)
2489 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2491 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2492 permutation |= SHADERPERMUTATION_REFLECTION;
2493 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2494 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2495 if (rsurface.texture->reflectmasktexture)
2496 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2497 if (FAKELIGHT_ENABLED)
2499 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2500 mode = SHADERMODE_FAKELIGHT;
2501 permutation |= SHADERPERMUTATION_DIFFUSE;
2502 if (specularscale > 0)
2503 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2505 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2507 // deluxemapping (light direction texture)
2508 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2509 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2511 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2512 permutation |= SHADERPERMUTATION_DIFFUSE;
2513 if (specularscale > 0)
2514 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2516 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2518 // fake deluxemapping (uniform light direction in tangentspace)
2519 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2520 permutation |= SHADERPERMUTATION_DIFFUSE;
2521 if (specularscale > 0)
2522 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2524 else if (rsurface.uselightmaptexture)
2526 // ordinary lightmapping (q1bsp, q3bsp)
2527 mode = SHADERMODE_LIGHTMAP;
2531 // ordinary vertex coloring (q3bsp)
2532 mode = SHADERMODE_VERTEXCOLOR;
2534 if (r_shadow_bouncegridtexture)
2535 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2536 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2537 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2538 allow_fog = R_BlendFuncAllowsFog(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2541 colormod = dummy_colormod;
2542 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2543 allow_fog = allow_colormod; // we actually implement fog by colormodding with a color (f,f,f) for some f
2545 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2546 switch(vid.renderpath)
2548 case RENDERPATH_D3D9:
2550 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);
2551 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2552 R_SetupShader_SetPermutationHLSL(mode, permutation);
2553 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2554 if (mode == SHADERMODE_LIGHTSOURCE)
2556 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2557 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2561 if (mode == SHADERMODE_LIGHTDIRECTION)
2563 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2566 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2567 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2568 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2569 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2570 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2572 if (mode == SHADERMODE_LIGHTSOURCE)
2574 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2575 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2576 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2577 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2578 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2580 // additive passes are only darkened by fog, not tinted
2581 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2582 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2586 if (mode == SHADERMODE_FLATCOLOR)
2588 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2590 else if (mode == SHADERMODE_LIGHTDIRECTION)
2592 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]);
2593 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2594 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);
2595 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);
2596 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2597 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2598 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2602 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2603 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2604 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);
2605 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);
2606 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2608 // additive passes are only darkened by fog, not tinted
2609 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2610 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2612 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2613 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);
2614 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2615 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2616 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2617 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2618 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2619 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2620 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2621 if (mode == SHADERMODE_WATER)
2622 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2624 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2625 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2626 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2627 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));
2628 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2629 if (rsurface.texture->pantstexture)
2630 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2632 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2633 if (rsurface.texture->shirttexture)
2634 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2636 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2637 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2638 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2639 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2640 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2641 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
2642 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2643 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2645 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2646 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2647 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2648 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2649 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2650 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2651 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2652 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2653 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2654 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2655 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2656 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2657 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2658 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2659 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2660 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2661 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2662 if (rsurfacepass == RSURFPASS_BACKGROUND)
2664 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2665 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2666 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2670 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2672 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2673 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2674 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2675 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2676 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2678 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2679 if (rsurface.rtlight)
2681 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2682 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2687 case RENDERPATH_D3D10:
2688 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2690 case RENDERPATH_D3D11:
2691 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2693 case RENDERPATH_GL20:
2694 case RENDERPATH_GLES2:
2695 if (!vid.useinterleavedarrays)
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_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2699 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2700 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2701 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2702 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2703 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2704 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2708 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);
2709 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2711 R_SetupShader_SetPermutationGLSL(mode, permutation);
2712 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2713 if (mode == SHADERMODE_LIGHTSOURCE)
2715 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2716 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2717 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2718 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2719 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2720 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);
2722 // additive passes are only darkened by fog, not tinted
2723 if (r_glsl_permutation->loc_FogColor >= 0)
2724 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2725 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2729 if (mode == SHADERMODE_FLATCOLOR)
2731 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2733 else if (mode == SHADERMODE_LIGHTDIRECTION)
2735 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]);
2736 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]);
2737 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);
2738 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);
2739 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);
2740 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]);
2741 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]);
2745 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]);
2746 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]);
2747 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);
2748 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);
2749 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);
2751 // additive passes are only darkened by fog, not tinted
2752 if (r_glsl_permutation->loc_FogColor >= 0)
2754 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2755 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2757 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2759 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);
2760 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]);
2761 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]);
2762 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]);
2763 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]);
2764 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2765 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2766 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2767 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]);
2769 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2770 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2771 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2772 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]);
2773 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]);
2775 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2776 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));
2777 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2778 if (r_glsl_permutation->loc_Color_Pants >= 0)
2780 if (rsurface.texture->pantstexture)
2781 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2783 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2785 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2787 if (rsurface.texture->shirttexture)
2788 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2790 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2792 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]);
2793 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2794 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2795 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2796 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
2797 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]);
2798 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2799 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);}
2800 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity);
2802 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2803 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2804 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2805 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2806 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2807 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2808 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2809 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2810 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2811 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2812 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2813 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2814 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2815 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2816 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);
2817 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2818 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2819 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2820 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2821 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2822 if (rsurfacepass == RSURFPASS_BACKGROUND)
2824 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);
2825 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);
2826 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);
2830 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);
2832 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2833 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2834 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2835 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2836 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2838 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
2839 if (rsurface.rtlight)
2841 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2842 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2845 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2848 case RENDERPATH_GL13:
2849 case RENDERPATH_GL11:
2851 case RENDERPATH_SOFT:
2852 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);
2853 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2854 R_SetupShader_SetPermutationSoft(mode, permutation);
2855 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2856 if (mode == SHADERMODE_LIGHTSOURCE)
2858 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2859 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2860 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2861 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2862 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2863 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2865 // additive passes are only darkened by fog, not tinted
2866 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2867 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2871 if (mode == SHADERMODE_FLATCOLOR)
2873 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2875 else if (mode == SHADERMODE_LIGHTDIRECTION)
2877 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]);
2878 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2879 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);
2880 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);
2881 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2882 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]);
2883 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2887 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2888 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2889 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);
2890 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);
2891 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2893 // additive passes are only darkened by fog, not tinted
2894 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2895 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2897 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2898 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);
2899 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2900 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2901 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]);
2902 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]);
2903 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2904 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2905 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2906 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2908 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2909 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2910 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2911 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2912 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]);
2914 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2915 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));
2916 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2917 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2919 if (rsurface.texture->pantstexture)
2920 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2922 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2924 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2926 if (rsurface.texture->shirttexture)
2927 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2929 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2931 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2932 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2933 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2934 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2935 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
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_NORMAL , rsurface.texture->nmaptexture );
2940 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2941 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2942 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2943 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2944 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2945 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2946 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2947 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2948 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2949 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2950 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2951 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2952 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2953 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2954 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2955 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2956 if (rsurfacepass == RSURFPASS_BACKGROUND)
2958 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2959 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2960 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2964 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2966 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2967 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2968 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2969 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2970 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2972 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2973 if (rsurface.rtlight)
2975 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2976 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2983 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2985 // select a permutation of the lighting shader appropriate to this
2986 // combination of texture, entity, light source, and fogging, only use the
2987 // minimum features necessary to avoid wasting rendering time in the
2988 // fragment shader on features that are not being used
2989 unsigned int permutation = 0;
2990 unsigned int mode = 0;
2991 const float *lightcolorbase = rtlight->currentcolor;
2992 float ambientscale = rtlight->ambientscale;
2993 float diffusescale = rtlight->diffusescale;
2994 float specularscale = rtlight->specularscale;
2995 // this is the location of the light in view space
2996 vec3_t viewlightorigin;
2997 // this transforms from view space (camera) to light space (cubemap)
2998 matrix4x4_t viewtolight;
2999 matrix4x4_t lighttoview;
3000 float viewtolight16f[16];
3001 float range = 1.0f / r_shadow_deferred_8bitrange.value;
3003 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3004 if (rtlight->currentcubemap != r_texture_whitecube)
3005 permutation |= SHADERPERMUTATION_CUBEFILTER;
3006 if (diffusescale > 0)
3007 permutation |= SHADERPERMUTATION_DIFFUSE;
3008 if (specularscale > 0)
3009 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3010 if (r_shadow_usingshadowmap2d)
3012 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3013 if (r_shadow_shadowmapvsdct)
3014 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3016 if (r_shadow_shadowmapsampler)
3017 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
3018 if (r_shadow_shadowmappcf > 1)
3019 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
3020 else if (r_shadow_shadowmappcf)
3021 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
3023 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3024 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3025 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3026 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3027 switch(vid.renderpath)
3029 case RENDERPATH_D3D9:
3031 R_SetupShader_SetPermutationHLSL(mode, permutation);
3032 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3033 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3034 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
3035 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
3036 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3037 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3038 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3039 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
3040 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3041 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3043 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3044 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
3045 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3046 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3047 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
3048 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3051 case RENDERPATH_D3D10:
3052 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3054 case RENDERPATH_D3D11:
3055 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3057 case RENDERPATH_GL20:
3058 case RENDERPATH_GLES2:
3059 R_SetupShader_SetPermutationGLSL(mode, permutation);
3060 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3061 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
3062 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);
3063 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);
3064 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);
3065 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]);
3066 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]);
3067 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));
3068 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]);
3069 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
3071 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
3072 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
3073 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
3074 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
3075 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
3076 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
3078 case RENDERPATH_GL13:
3079 case RENDERPATH_GL11:
3081 case RENDERPATH_SOFT:
3082 R_SetupShader_SetPermutationGLSL(mode, permutation);
3083 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3084 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
3085 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
3086 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
3087 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3088 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3089 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]);
3090 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));
3091 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3092 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3094 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3095 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
3096 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3097 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3098 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
3099 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3104 #define SKINFRAME_HASH 1024
3108 int loadsequence; // incremented each level change
3109 memexpandablearray_t array;
3110 skinframe_t *hash[SKINFRAME_HASH];
3113 r_skinframe_t r_skinframe;
3115 void R_SkinFrame_PrepareForPurge(void)
3117 r_skinframe.loadsequence++;
3118 // wrap it without hitting zero
3119 if (r_skinframe.loadsequence >= 200)
3120 r_skinframe.loadsequence = 1;
3123 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3127 // mark the skinframe as used for the purging code
3128 skinframe->loadsequence = r_skinframe.loadsequence;
3131 void R_SkinFrame_Purge(void)
3135 for (i = 0;i < SKINFRAME_HASH;i++)
3137 for (s = r_skinframe.hash[i];s;s = s->next)
3139 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3141 if (s->merged == s->base)
3143 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3144 R_PurgeTexture(s->stain );s->stain = NULL;
3145 R_PurgeTexture(s->merged);s->merged = NULL;
3146 R_PurgeTexture(s->base );s->base = NULL;
3147 R_PurgeTexture(s->pants );s->pants = NULL;
3148 R_PurgeTexture(s->shirt );s->shirt = NULL;
3149 R_PurgeTexture(s->nmap );s->nmap = NULL;
3150 R_PurgeTexture(s->gloss );s->gloss = NULL;
3151 R_PurgeTexture(s->glow );s->glow = NULL;
3152 R_PurgeTexture(s->fog );s->fog = NULL;
3153 R_PurgeTexture(s->reflect);s->reflect = NULL;
3154 s->loadsequence = 0;
3160 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3162 char basename[MAX_QPATH];
3164 Image_StripImageExtension(name, basename, sizeof(basename));
3166 if( last == NULL ) {
3168 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3169 item = r_skinframe.hash[hashindex];
3174 // linearly search through the hash bucket
3175 for( ; item ; item = item->next ) {
3176 if( !strcmp( item->basename, basename ) ) {
3183 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3187 char basename[MAX_QPATH];
3189 Image_StripImageExtension(name, basename, sizeof(basename));
3191 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3192 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3193 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3197 rtexture_t *dyntexture;
3198 // check whether its a dynamic texture
3199 dyntexture = CL_GetDynTexture( basename );
3200 if (!add && !dyntexture)
3202 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3203 memset(item, 0, sizeof(*item));
3204 strlcpy(item->basename, basename, sizeof(item->basename));
3205 item->base = dyntexture; // either NULL or dyntexture handle
3206 item->textureflags = textureflags;
3207 item->comparewidth = comparewidth;
3208 item->compareheight = compareheight;
3209 item->comparecrc = comparecrc;
3210 item->next = r_skinframe.hash[hashindex];
3211 r_skinframe.hash[hashindex] = item;
3213 else if( item->base == NULL )
3215 rtexture_t *dyntexture;
3216 // check whether its a dynamic texture
3217 // 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]
3218 dyntexture = CL_GetDynTexture( basename );
3219 item->base = dyntexture; // either NULL or dyntexture handle
3222 R_SkinFrame_MarkUsed(item);
3226 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3228 unsigned long long avgcolor[5], wsum; \
3236 for(pix = 0; pix < cnt; ++pix) \
3239 for(comp = 0; comp < 3; ++comp) \
3241 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3244 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3246 for(comp = 0; comp < 3; ++comp) \
3247 avgcolor[comp] += getpixel * w; \
3250 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3251 avgcolor[4] += getpixel; \
3253 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3255 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3256 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3257 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3258 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3261 extern cvar_t gl_picmip;
3262 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3265 unsigned char *pixels;
3266 unsigned char *bumppixels;
3267 unsigned char *basepixels = NULL;
3268 int basepixels_width = 0;
3269 int basepixels_height = 0;
3270 skinframe_t *skinframe;
3271 rtexture_t *ddsbase = NULL;
3272 qboolean ddshasalpha = false;
3273 float ddsavgcolor[4];
3274 char basename[MAX_QPATH];
3275 int miplevel = R_PicmipForFlags(textureflags);
3276 int savemiplevel = miplevel;
3279 if (cls.state == ca_dedicated)
3282 // return an existing skinframe if already loaded
3283 // if loading of the first image fails, don't make a new skinframe as it
3284 // would cause all future lookups of this to be missing
3285 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3286 if (skinframe && skinframe->base)
3289 Image_StripImageExtension(name, basename, sizeof(basename));
3291 // check for DDS texture file first
3292 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3294 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
3295 if (basepixels == NULL)
3299 // FIXME handle miplevel
3301 if (developer_loading.integer)
3302 Con_Printf("loading skin \"%s\"\n", name);
3304 // we've got some pixels to store, so really allocate this new texture now
3306 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3307 skinframe->stain = NULL;
3308 skinframe->merged = NULL;
3309 skinframe->base = NULL;
3310 skinframe->pants = NULL;
3311 skinframe->shirt = NULL;
3312 skinframe->nmap = NULL;
3313 skinframe->gloss = NULL;
3314 skinframe->glow = NULL;
3315 skinframe->fog = NULL;
3316 skinframe->reflect = NULL;
3317 skinframe->hasalpha = false;
3321 skinframe->base = ddsbase;
3322 skinframe->hasalpha = ddshasalpha;
3323 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3324 if (r_loadfog && skinframe->hasalpha)
3325 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3326 //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]);
3330 basepixels_width = image_width;
3331 basepixels_height = image_height;
3332 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);
3333 if (textureflags & TEXF_ALPHA)
3335 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3337 if (basepixels[j] < 255)
3339 skinframe->hasalpha = true;
3343 if (r_loadfog && skinframe->hasalpha)
3345 // has transparent pixels
3346 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3347 for (j = 0;j < image_width * image_height * 4;j += 4)
3352 pixels[j+3] = basepixels[j+3];
3354 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);
3358 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3359 //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]);
3360 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3361 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
3362 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3363 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
3368 mymiplevel = savemiplevel;
3369 if (r_loadnormalmap)
3370 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);
3371 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3373 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3374 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3375 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3376 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3379 // _norm is the name used by tenebrae and has been adopted as standard
3380 if (r_loadnormalmap && skinframe->nmap == NULL)
3382 mymiplevel = savemiplevel;
3383 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3385 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);
3389 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3391 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3392 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3393 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);
3395 Mem_Free(bumppixels);
3397 else if (r_shadow_bumpscale_basetexture.value > 0)
3399 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3400 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3401 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);
3404 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3405 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
3408 // _luma is supported only for tenebrae compatibility
3409 // _glow is the preferred name
3410 mymiplevel = savemiplevel;
3411 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))))
3413 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);
3414 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3415 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
3416 Mem_Free(pixels);pixels = NULL;
3419 mymiplevel = savemiplevel;
3420 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3422 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);
3423 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3424 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
3429 mymiplevel = savemiplevel;
3430 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3432 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);
3433 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3434 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
3439 mymiplevel = savemiplevel;
3440 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3442 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);
3443 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3444 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
3449 mymiplevel = savemiplevel;
3450 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3452 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);
3453 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3454 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
3460 Mem_Free(basepixels);
3465 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3466 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
3469 unsigned char *temp1, *temp2;
3470 skinframe_t *skinframe;
3472 if (cls.state == ca_dedicated)
3475 // if already loaded just return it, otherwise make a new skinframe
3476 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3477 if (skinframe && skinframe->base)
3480 skinframe->stain = NULL;
3481 skinframe->merged = NULL;
3482 skinframe->base = NULL;
3483 skinframe->pants = NULL;
3484 skinframe->shirt = NULL;
3485 skinframe->nmap = NULL;
3486 skinframe->gloss = NULL;
3487 skinframe->glow = NULL;
3488 skinframe->fog = NULL;
3489 skinframe->reflect = NULL;
3490 skinframe->hasalpha = false;
3492 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3496 if (developer_loading.integer)
3497 Con_Printf("loading 32bit skin \"%s\"\n", name);
3499 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3501 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3502 temp2 = temp1 + width * height * 4;
3503 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3504 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);
3507 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
3508 if (textureflags & TEXF_ALPHA)
3510 for (i = 3;i < width * height * 4;i += 4)
3512 if (skindata[i] < 255)
3514 skinframe->hasalpha = true;
3518 if (r_loadfog && skinframe->hasalpha)
3520 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3521 memcpy(fogpixels, skindata, width * height * 4);
3522 for (i = 0;i < width * height * 4;i += 4)
3523 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3524 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3525 Mem_Free(fogpixels);
3529 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3530 //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]);
3535 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3539 skinframe_t *skinframe;
3541 if (cls.state == ca_dedicated)
3544 // if already loaded just return it, otherwise make a new skinframe
3545 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3546 if (skinframe && skinframe->base)
3549 skinframe->stain = NULL;
3550 skinframe->merged = NULL;
3551 skinframe->base = NULL;
3552 skinframe->pants = NULL;
3553 skinframe->shirt = NULL;
3554 skinframe->nmap = NULL;
3555 skinframe->gloss = NULL;
3556 skinframe->glow = NULL;
3557 skinframe->fog = NULL;
3558 skinframe->reflect = NULL;
3559 skinframe->hasalpha = false;
3561 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3565 if (developer_loading.integer)
3566 Con_Printf("loading quake skin \"%s\"\n", name);
3568 // 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)
3569 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3570 memcpy(skinframe->qpixels, skindata, width*height);
3571 skinframe->qwidth = width;
3572 skinframe->qheight = height;
3575 for (i = 0;i < width * height;i++)
3576 featuresmask |= palette_featureflags[skindata[i]];
3578 skinframe->hasalpha = false;
3579 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3580 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3581 skinframe->qgeneratemerged = true;
3582 skinframe->qgeneratebase = skinframe->qhascolormapping;
3583 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3585 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3586 //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]);
3591 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3595 unsigned char *skindata;
3597 if (!skinframe->qpixels)
3600 if (!skinframe->qhascolormapping)
3601 colormapped = false;
3605 if (!skinframe->qgeneratebase)
3610 if (!skinframe->qgeneratemerged)
3614 width = skinframe->qwidth;
3615 height = skinframe->qheight;
3616 skindata = skinframe->qpixels;
3618 if (skinframe->qgeneratenmap)
3620 unsigned char *temp1, *temp2;
3621 skinframe->qgeneratenmap = false;
3622 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3623 temp2 = temp1 + width * height * 4;
3624 // use either a custom palette or the quake palette
3625 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3626 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3627 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);
3631 if (skinframe->qgenerateglow)
3633 skinframe->qgenerateglow = false;
3634 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3639 skinframe->qgeneratebase = false;
3640 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);
3641 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3642 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3646 skinframe->qgeneratemerged = false;
3647 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);
3650 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3652 Mem_Free(skinframe->qpixels);
3653 skinframe->qpixels = NULL;
3657 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)
3660 skinframe_t *skinframe;
3662 if (cls.state == ca_dedicated)
3665 // if already loaded just return it, otherwise make a new skinframe
3666 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3667 if (skinframe && skinframe->base)
3670 skinframe->stain = NULL;
3671 skinframe->merged = NULL;
3672 skinframe->base = NULL;
3673 skinframe->pants = NULL;
3674 skinframe->shirt = NULL;
3675 skinframe->nmap = NULL;
3676 skinframe->gloss = NULL;
3677 skinframe->glow = NULL;
3678 skinframe->fog = NULL;
3679 skinframe->reflect = NULL;
3680 skinframe->hasalpha = false;
3682 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3686 if (developer_loading.integer)
3687 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3689 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3690 if (textureflags & TEXF_ALPHA)
3692 for (i = 0;i < width * height;i++)
3694 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3696 skinframe->hasalpha = true;
3700 if (r_loadfog && skinframe->hasalpha)
3701 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3704 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3705 //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]);
3710 skinframe_t *R_SkinFrame_LoadMissing(void)
3712 skinframe_t *skinframe;
3714 if (cls.state == ca_dedicated)
3717 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3718 skinframe->stain = NULL;
3719 skinframe->merged = NULL;
3720 skinframe->base = NULL;
3721 skinframe->pants = NULL;
3722 skinframe->shirt = NULL;
3723 skinframe->nmap = NULL;
3724 skinframe->gloss = NULL;
3725 skinframe->glow = NULL;
3726 skinframe->fog = NULL;
3727 skinframe->reflect = NULL;
3728 skinframe->hasalpha = false;
3730 skinframe->avgcolor[0] = rand() / RAND_MAX;
3731 skinframe->avgcolor[1] = rand() / RAND_MAX;
3732 skinframe->avgcolor[2] = rand() / RAND_MAX;
3733 skinframe->avgcolor[3] = 1;
3738 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3739 typedef struct suffixinfo_s
3742 qboolean flipx, flipy, flipdiagonal;
3745 static suffixinfo_t suffix[3][6] =
3748 {"px", false, false, false},
3749 {"nx", false, false, false},
3750 {"py", false, false, false},
3751 {"ny", false, false, false},
3752 {"pz", false, false, false},
3753 {"nz", false, false, false}
3756 {"posx", false, false, false},
3757 {"negx", false, false, false},
3758 {"posy", false, false, false},
3759 {"negy", false, false, false},
3760 {"posz", false, false, false},
3761 {"negz", false, false, false}
3764 {"rt", true, false, true},
3765 {"lf", false, true, true},
3766 {"ft", true, true, false},
3767 {"bk", false, false, false},
3768 {"up", true, false, true},
3769 {"dn", true, false, true}
3773 static int componentorder[4] = {0, 1, 2, 3};
3775 rtexture_t *R_LoadCubemap(const char *basename)
3777 int i, j, cubemapsize;
3778 unsigned char *cubemappixels, *image_buffer;
3779 rtexture_t *cubemaptexture;
3781 // must start 0 so the first loadimagepixels has no requested width/height
3783 cubemappixels = NULL;
3784 cubemaptexture = NULL;
3785 // keep trying different suffix groups (posx, px, rt) until one loads
3786 for (j = 0;j < 3 && !cubemappixels;j++)
3788 // load the 6 images in the suffix group
3789 for (i = 0;i < 6;i++)
3791 // generate an image name based on the base and and suffix
3792 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3794 if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
3796 // an image loaded, make sure width and height are equal
3797 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3799 // if this is the first image to load successfully, allocate the cubemap memory
3800 if (!cubemappixels && image_width >= 1)
3802 cubemapsize = image_width;
3803 // note this clears to black, so unavailable sides are black
3804 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3806 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3808 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);
3811 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3813 Mem_Free(image_buffer);
3817 // if a cubemap loaded, upload it
3820 if (developer_loading.integer)
3821 Con_Printf("loading cubemap \"%s\"\n", basename);
3823 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3824 Mem_Free(cubemappixels);
3828 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3829 if (developer_loading.integer)
3831 Con_Printf("(tried tried images ");
3832 for (j = 0;j < 3;j++)
3833 for (i = 0;i < 6;i++)
3834 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3835 Con_Print(" and was unable to find any of them).\n");
3838 return cubemaptexture;
3841 rtexture_t *R_GetCubemap(const char *basename)
3844 for (i = 0;i < r_texture_numcubemaps;i++)
3845 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3846 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3847 if (i >= MAX_CUBEMAPS)
3848 return r_texture_whitecube;
3849 r_texture_numcubemaps++;
3850 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3851 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3852 return r_texture_cubemaps[i].texture;
3855 void R_FreeCubemaps(void)
3858 for (i = 0;i < r_texture_numcubemaps;i++)
3860 if (developer_loading.integer)
3861 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3862 if (r_texture_cubemaps[i].texture)
3863 R_FreeTexture(r_texture_cubemaps[i].texture);
3865 r_texture_numcubemaps = 0;
3868 void R_Main_FreeViewCache(void)
3870 if (r_refdef.viewcache.entityvisible)
3871 Mem_Free(r_refdef.viewcache.entityvisible);
3872 if (r_refdef.viewcache.world_pvsbits)
3873 Mem_Free(r_refdef.viewcache.world_pvsbits);
3874 if (r_refdef.viewcache.world_leafvisible)
3875 Mem_Free(r_refdef.viewcache.world_leafvisible);
3876 if (r_refdef.viewcache.world_surfacevisible)
3877 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3878 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3881 void R_Main_ResizeViewCache(void)
3883 int numentities = r_refdef.scene.numentities;
3884 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3885 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3886 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3887 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3888 if (r_refdef.viewcache.maxentities < numentities)
3890 r_refdef.viewcache.maxentities = numentities;
3891 if (r_refdef.viewcache.entityvisible)
3892 Mem_Free(r_refdef.viewcache.entityvisible);
3893 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3895 if (r_refdef.viewcache.world_numclusters != numclusters)
3897 r_refdef.viewcache.world_numclusters = numclusters;
3898 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3899 if (r_refdef.viewcache.world_pvsbits)
3900 Mem_Free(r_refdef.viewcache.world_pvsbits);
3901 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3903 if (r_refdef.viewcache.world_numleafs != numleafs)
3905 r_refdef.viewcache.world_numleafs = numleafs;
3906 if (r_refdef.viewcache.world_leafvisible)
3907 Mem_Free(r_refdef.viewcache.world_leafvisible);
3908 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3910 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3912 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3913 if (r_refdef.viewcache.world_surfacevisible)
3914 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3915 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3919 extern rtexture_t *loadingscreentexture;
3920 void gl_main_start(void)
3922 loadingscreentexture = NULL;
3923 r_texture_blanknormalmap = NULL;
3924 r_texture_white = NULL;
3925 r_texture_grey128 = NULL;
3926 r_texture_black = NULL;
3927 r_texture_whitecube = NULL;
3928 r_texture_normalizationcube = NULL;
3929 r_texture_fogattenuation = NULL;
3930 r_texture_fogheighttexture = NULL;
3931 r_texture_gammaramps = NULL;
3932 r_texture_numcubemaps = 0;
3934 r_loaddds = r_texture_dds_load.integer != 0;
3935 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3937 switch(vid.renderpath)
3939 case RENDERPATH_GL20:
3940 case RENDERPATH_D3D9:
3941 case RENDERPATH_D3D10:
3942 case RENDERPATH_D3D11:
3943 case RENDERPATH_SOFT:
3944 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3945 Cvar_SetValueQuick(&gl_combine, 1);
3946 Cvar_SetValueQuick(&r_glsl, 1);
3947 r_loadnormalmap = true;
3951 case RENDERPATH_GL13:
3952 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3953 Cvar_SetValueQuick(&gl_combine, 1);
3954 Cvar_SetValueQuick(&r_glsl, 0);
3955 r_loadnormalmap = false;
3956 r_loadgloss = false;
3959 case RENDERPATH_GL11:
3960 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3961 Cvar_SetValueQuick(&gl_combine, 0);
3962 Cvar_SetValueQuick(&r_glsl, 0);
3963 r_loadnormalmap = false;
3964 r_loadgloss = false;
3967 case RENDERPATH_GLES2:
3968 Cvar_SetValueQuick(&r_textureunits, 1);
3969 Cvar_SetValueQuick(&gl_combine, 1);
3970 Cvar_SetValueQuick(&r_glsl, 1);
3971 r_loadnormalmap = true;
3972 r_loadgloss = false;
3978 R_FrameData_Reset();
3982 memset(r_queries, 0, sizeof(r_queries));
3984 r_qwskincache = NULL;
3985 r_qwskincache_size = 0;
3987 // set up r_skinframe loading system for textures
3988 memset(&r_skinframe, 0, sizeof(r_skinframe));
3989 r_skinframe.loadsequence = 1;
3990 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3992 r_main_texturepool = R_AllocTexturePool();
3993 R_BuildBlankTextures();
3995 if (vid.support.arb_texture_cube_map)
3998 R_BuildNormalizationCube();
4000 r_texture_fogattenuation = NULL;
4001 r_texture_fogheighttexture = NULL;
4002 r_texture_gammaramps = NULL;
4003 //r_texture_fogintensity = NULL;
4004 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4005 memset(&r_waterstate, 0, sizeof(r_waterstate));
4006 r_glsl_permutation = NULL;
4007 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4008 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4009 glslshaderstring = NULL;
4011 r_hlsl_permutation = NULL;
4012 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4013 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4015 hlslshaderstring = NULL;
4016 memset(&r_svbsp, 0, sizeof (r_svbsp));
4018 r_refdef.fogmasktable_density = 0;
4021 void gl_main_shutdown(void)
4024 R_FrameData_Reset();
4026 R_Main_FreeViewCache();
4028 switch(vid.renderpath)
4030 case RENDERPATH_GL11:
4031 case RENDERPATH_GL13:
4032 case RENDERPATH_GL20:
4033 case RENDERPATH_GLES2:
4035 qglDeleteQueriesARB(r_maxqueries, r_queries);
4037 case RENDERPATH_D3D9:
4038 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4040 case RENDERPATH_D3D10:
4041 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4043 case RENDERPATH_D3D11:
4044 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4046 case RENDERPATH_SOFT:
4052 memset(r_queries, 0, sizeof(r_queries));
4054 r_qwskincache = NULL;
4055 r_qwskincache_size = 0;
4057 // clear out the r_skinframe state
4058 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4059 memset(&r_skinframe, 0, sizeof(r_skinframe));
4062 Mem_Free(r_svbsp.nodes);
4063 memset(&r_svbsp, 0, sizeof (r_svbsp));
4064 R_FreeTexturePool(&r_main_texturepool);
4065 loadingscreentexture = NULL;
4066 r_texture_blanknormalmap = NULL;
4067 r_texture_white = NULL;
4068 r_texture_grey128 = NULL;
4069 r_texture_black = NULL;
4070 r_texture_whitecube = NULL;
4071 r_texture_normalizationcube = NULL;
4072 r_texture_fogattenuation = NULL;
4073 r_texture_fogheighttexture = NULL;
4074 r_texture_gammaramps = NULL;
4075 r_texture_numcubemaps = 0;
4076 //r_texture_fogintensity = NULL;
4077 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4078 memset(&r_waterstate, 0, sizeof(r_waterstate));
4081 r_glsl_permutation = NULL;
4082 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4083 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4084 glslshaderstring = NULL;
4086 r_hlsl_permutation = NULL;
4087 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4088 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4090 hlslshaderstring = NULL;
4093 extern void CL_ParseEntityLump(char *entitystring);
4094 void gl_main_newmap(void)
4096 // FIXME: move this code to client
4097 char *entities, entname[MAX_QPATH];
4099 Mem_Free(r_qwskincache);
4100 r_qwskincache = NULL;
4101 r_qwskincache_size = 0;
4104 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4105 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4107 CL_ParseEntityLump(entities);
4111 if (cl.worldmodel->brush.entities)
4112 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4114 R_Main_FreeViewCache();
4116 R_FrameData_Reset();
4119 void GL_Main_Init(void)
4121 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4123 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4124 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4125 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4126 if (gamemode == GAME_NEHAHRA)
4128 Cvar_RegisterVariable (&gl_fogenable);
4129 Cvar_RegisterVariable (&gl_fogdensity);
4130 Cvar_RegisterVariable (&gl_fogred);
4131 Cvar_RegisterVariable (&gl_foggreen);
4132 Cvar_RegisterVariable (&gl_fogblue);
4133 Cvar_RegisterVariable (&gl_fogstart);
4134 Cvar_RegisterVariable (&gl_fogend);
4135 Cvar_RegisterVariable (&gl_skyclip);
4137 Cvar_RegisterVariable(&r_motionblur);
4138 Cvar_RegisterVariable(&r_motionblur_maxblur);
4139 Cvar_RegisterVariable(&r_motionblur_bmin);
4140 Cvar_RegisterVariable(&r_motionblur_vmin);
4141 Cvar_RegisterVariable(&r_motionblur_vmax);
4142 Cvar_RegisterVariable(&r_motionblur_vcoeff);
4143 Cvar_RegisterVariable(&r_motionblur_randomize);
4144 Cvar_RegisterVariable(&r_damageblur);
4145 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4146 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4147 Cvar_RegisterVariable(&r_equalize_entities_by);
4148 Cvar_RegisterVariable(&r_equalize_entities_to);
4149 Cvar_RegisterVariable(&r_depthfirst);
4150 Cvar_RegisterVariable(&r_useinfinitefarclip);
4151 Cvar_RegisterVariable(&r_farclip_base);
4152 Cvar_RegisterVariable(&r_farclip_world);
4153 Cvar_RegisterVariable(&r_nearclip);
4154 Cvar_RegisterVariable(&r_showbboxes);
4155 Cvar_RegisterVariable(&r_showsurfaces);
4156 Cvar_RegisterVariable(&r_showtris);
4157 Cvar_RegisterVariable(&r_shownormals);
4158 Cvar_RegisterVariable(&r_showlighting);
4159 Cvar_RegisterVariable(&r_showshadowvolumes);
4160 Cvar_RegisterVariable(&r_showcollisionbrushes);
4161 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4162 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4163 Cvar_RegisterVariable(&r_showdisabledepthtest);
4164 Cvar_RegisterVariable(&r_drawportals);
4165 Cvar_RegisterVariable(&r_drawentities);
4166 Cvar_RegisterVariable(&r_draw2d);
4167 Cvar_RegisterVariable(&r_drawworld);
4168 Cvar_RegisterVariable(&r_cullentities_trace);
4169 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4170 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4171 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4172 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4173 Cvar_RegisterVariable(&r_drawviewmodel);
4174 Cvar_RegisterVariable(&r_drawexteriormodel);
4175 Cvar_RegisterVariable(&r_speeds);
4176 Cvar_RegisterVariable(&r_fullbrights);
4177 Cvar_RegisterVariable(&r_wateralpha);
4178 Cvar_RegisterVariable(&r_dynamic);
4179 Cvar_RegisterVariable(&r_fakelight);
4180 Cvar_RegisterVariable(&r_fakelight_intensity);
4181 Cvar_RegisterVariable(&r_fullbright);
4182 Cvar_RegisterVariable(&r_shadows);
4183 Cvar_RegisterVariable(&r_shadows_darken);
4184 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4185 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4186 Cvar_RegisterVariable(&r_shadows_throwdistance);
4187 Cvar_RegisterVariable(&r_shadows_throwdirection);
4188 Cvar_RegisterVariable(&r_shadows_focus);
4189 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4190 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4191 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4192 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4193 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4194 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4195 Cvar_RegisterVariable(&r_fog_exp2);
4196 Cvar_RegisterVariable(&r_drawfog);
4197 Cvar_RegisterVariable(&r_transparentdepthmasking);
4198 Cvar_RegisterVariable(&r_texture_dds_load);
4199 Cvar_RegisterVariable(&r_texture_dds_save);
4200 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
4201 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
4202 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
4203 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
4204 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
4205 Cvar_RegisterVariable(&r_textureunits);
4206 Cvar_RegisterVariable(&gl_combine);
4207 Cvar_RegisterVariable(&r_glsl);
4208 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4209 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4210 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4211 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4212 Cvar_RegisterVariable(&r_glsl_postprocess);
4213 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4214 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4215 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4216 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4217 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4218 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4219 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4220 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4222 Cvar_RegisterVariable(&r_water);
4223 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4224 Cvar_RegisterVariable(&r_water_clippingplanebias);
4225 Cvar_RegisterVariable(&r_water_refractdistort);
4226 Cvar_RegisterVariable(&r_water_reflectdistort);
4227 Cvar_RegisterVariable(&r_water_scissormode);
4228 Cvar_RegisterVariable(&r_lerpsprites);
4229 Cvar_RegisterVariable(&r_lerpmodels);
4230 Cvar_RegisterVariable(&r_lerplightstyles);
4231 Cvar_RegisterVariable(&r_waterscroll);
4232 Cvar_RegisterVariable(&r_bloom);
4233 Cvar_RegisterVariable(&r_bloom_colorscale);
4234 Cvar_RegisterVariable(&r_bloom_brighten);
4235 Cvar_RegisterVariable(&r_bloom_blur);
4236 Cvar_RegisterVariable(&r_bloom_resolution);
4237 Cvar_RegisterVariable(&r_bloom_colorexponent);
4238 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4239 Cvar_RegisterVariable(&r_hdr);
4240 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4241 Cvar_RegisterVariable(&r_hdr_glowintensity);
4242 Cvar_RegisterVariable(&r_hdr_range);
4243 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4244 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4245 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4246 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4247 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4248 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4249 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4250 Cvar_RegisterVariable(&developer_texturelogging);
4251 Cvar_RegisterVariable(&gl_lightmaps);
4252 Cvar_RegisterVariable(&r_test);
4253 Cvar_RegisterVariable(&r_glsl_saturation);
4254 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4255 Cvar_RegisterVariable(&r_framedatasize);
4256 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4257 Cvar_SetValue("r_fullbrights", 0);
4258 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4260 Cvar_RegisterVariable(&r_track_sprites);
4261 Cvar_RegisterVariable(&r_track_sprites_flags);
4262 Cvar_RegisterVariable(&r_track_sprites_scalew);
4263 Cvar_RegisterVariable(&r_track_sprites_scaleh);
4264 Cvar_RegisterVariable(&r_overheadsprites_perspective);
4265 Cvar_RegisterVariable(&r_overheadsprites_pushback);
4266 Cvar_RegisterVariable(&r_overheadsprites_scalex);
4267 Cvar_RegisterVariable(&r_overheadsprites_scaley);
4270 extern void R_Textures_Init(void);
4271 extern void GL_Draw_Init(void);
4272 extern void GL_Main_Init(void);
4273 extern void R_Shadow_Init(void);
4274 extern void R_Sky_Init(void);
4275 extern void GL_Surf_Init(void);
4276 extern void R_Particles_Init(void);
4277 extern void R_Explosion_Init(void);
4278 extern void gl_backend_init(void);
4279 extern void Sbar_Init(void);
4280 extern void R_LightningBeams_Init(void);
4281 extern void Mod_RenderInit(void);
4282 extern void Font_Init(void);
4284 void Render_Init(void)
4297 R_LightningBeams_Init();
4306 extern char *ENGINE_EXTENSIONS;
4309 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4310 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4311 gl_version = (const char *)qglGetString(GL_VERSION);
4312 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4316 if (!gl_platformextensions)
4317 gl_platformextensions = "";
4319 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4320 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4321 Con_Printf("GL_VERSION: %s\n", gl_version);
4322 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4323 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4325 VID_CheckExtensions();
4327 // LordHavoc: report supported extensions
4328 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4330 // clear to black (loading plaque will be seen over this)
4331 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4334 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4338 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4340 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4343 p = r_refdef.view.frustum + i;
4348 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4352 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4356 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4360 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4364 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4368 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4372 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4376 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4384 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4388 for (i = 0;i < numplanes;i++)
4395 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4399 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4403 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4407 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4411 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4415 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4419 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4423 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4431 //==================================================================================
4433 // LordHavoc: this stores temporary data used within the same frame
4435 typedef struct r_framedata_mem_s
4437 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4438 size_t size; // how much usable space
4439 size_t current; // how much space in use
4440 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4441 size_t wantedsize; // how much space was allocated
4442 unsigned char *data; // start of real data (16byte aligned)
4446 static r_framedata_mem_t *r_framedata_mem;
4448 void R_FrameData_Reset(void)
4450 while (r_framedata_mem)
4452 r_framedata_mem_t *next = r_framedata_mem->purge;
4453 Mem_Free(r_framedata_mem);
4454 r_framedata_mem = next;
4458 void R_FrameData_Resize(void)
4461 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4462 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4463 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4465 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4466 newmem->wantedsize = wantedsize;
4467 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4468 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4469 newmem->current = 0;
4471 newmem->purge = r_framedata_mem;
4472 r_framedata_mem = newmem;
4476 void R_FrameData_NewFrame(void)
4478 R_FrameData_Resize();
4479 if (!r_framedata_mem)
4481 // if we ran out of space on the last frame, free the old memory now
4482 while (r_framedata_mem->purge)
4484 // repeatedly remove the second item in the list, leaving only head
4485 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4486 Mem_Free(r_framedata_mem->purge);
4487 r_framedata_mem->purge = next;
4489 // reset the current mem pointer
4490 r_framedata_mem->current = 0;
4491 r_framedata_mem->mark = 0;
4494 void *R_FrameData_Alloc(size_t size)
4498 // align to 16 byte boundary - the data pointer is already aligned, so we
4499 // only need to ensure the size of every allocation is also aligned
4500 size = (size + 15) & ~15;
4502 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4504 // emergency - we ran out of space, allocate more memory
4505 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4506 R_FrameData_Resize();
4509 data = r_framedata_mem->data + r_framedata_mem->current;
4510 r_framedata_mem->current += size;
4512 // count the usage for stats
4513 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4514 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4516 return (void *)data;
4519 void *R_FrameData_Store(size_t size, void *data)
4521 void *d = R_FrameData_Alloc(size);
4523 memcpy(d, data, size);
4527 void R_FrameData_SetMark(void)
4529 if (!r_framedata_mem)
4531 r_framedata_mem->mark = r_framedata_mem->current;
4534 void R_FrameData_ReturnToMark(void)
4536 if (!r_framedata_mem)
4538 r_framedata_mem->current = r_framedata_mem->mark;
4541 //==================================================================================
4543 // LordHavoc: animcache originally written by Echon, rewritten since then
4546 * Animation cache prevents re-generating mesh data for an animated model
4547 * multiple times in one frame for lighting, shadowing, reflections, etc.
4550 void R_AnimCache_Free(void)
4554 void R_AnimCache_ClearCache(void)
4557 entity_render_t *ent;
4559 for (i = 0;i < r_refdef.scene.numentities;i++)
4561 ent = r_refdef.scene.entities[i];
4562 ent->animcache_vertex3f = NULL;
4563 ent->animcache_normal3f = NULL;
4564 ent->animcache_svector3f = NULL;
4565 ent->animcache_tvector3f = NULL;
4566 ent->animcache_vertexmesh = NULL;
4567 ent->animcache_vertex3fbuffer = NULL;
4568 ent->animcache_vertexmeshbuffer = NULL;
4572 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4576 // check if we need the meshbuffers
4577 if (!vid.useinterleavedarrays)
4580 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4581 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4582 // TODO: upload vertex3f buffer?
4583 if (ent->animcache_vertexmesh)
4585 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4586 for (i = 0;i < numvertices;i++)
4587 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4588 if (ent->animcache_svector3f)
4589 for (i = 0;i < numvertices;i++)
4590 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4591 if (ent->animcache_tvector3f)
4592 for (i = 0;i < numvertices;i++)
4593 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4594 if (ent->animcache_normal3f)
4595 for (i = 0;i < numvertices;i++)
4596 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4597 // TODO: upload vertexmeshbuffer?
4601 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4603 dp_model_t *model = ent->model;
4605 // see if it's already cached this frame
4606 if (ent->animcache_vertex3f)
4608 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4609 if (wantnormals || wanttangents)
4611 if (ent->animcache_normal3f)
4612 wantnormals = false;
4613 if (ent->animcache_svector3f)
4614 wanttangents = false;
4615 if (wantnormals || wanttangents)
4617 numvertices = model->surfmesh.num_vertices;
4619 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4622 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4623 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4625 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4626 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4632 // see if this ent is worth caching
4633 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4635 // get some memory for this entity and generate mesh data
4636 numvertices = model->surfmesh.num_vertices;
4637 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4639 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4642 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4643 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4645 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4646 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4651 void R_AnimCache_CacheVisibleEntities(void)
4654 qboolean wantnormals = true;
4655 qboolean wanttangents = !r_showsurfaces.integer;
4657 switch(vid.renderpath)
4659 case RENDERPATH_GL20:
4660 case RENDERPATH_D3D9:
4661 case RENDERPATH_D3D10:
4662 case RENDERPATH_D3D11:
4663 case RENDERPATH_GLES2:
4665 case RENDERPATH_GL13:
4666 case RENDERPATH_GL11:
4667 wanttangents = false;
4669 case RENDERPATH_SOFT:
4673 if (r_shownormals.integer)
4674 wanttangents = wantnormals = true;
4676 // TODO: thread this
4677 // NOTE: R_PrepareRTLights() also caches entities
4679 for (i = 0;i < r_refdef.scene.numentities;i++)
4680 if (r_refdef.viewcache.entityvisible[i])
4681 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4684 //==================================================================================
4686 static void R_View_UpdateEntityLighting (void)
4689 entity_render_t *ent;
4690 vec3_t tempdiffusenormal, avg;
4691 vec_t f, fa, fd, fdd;
4692 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4694 for (i = 0;i < r_refdef.scene.numentities;i++)
4696 ent = r_refdef.scene.entities[i];
4698 // skip unseen models
4699 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4703 if (ent->model && ent->model->brush.num_leafs)
4705 // TODO: use modellight for r_ambient settings on world?
4706 VectorSet(ent->modellight_ambient, 0, 0, 0);
4707 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4708 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4712 // fetch the lighting from the worldmodel data
4713 VectorClear(ent->modellight_ambient);
4714 VectorClear(ent->modellight_diffuse);
4715 VectorClear(tempdiffusenormal);
4716 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4719 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4721 // complete lightning for lit sprites
4722 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4723 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4725 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4726 org[2] = org[2] + r_overheadsprites_pushback.value;
4727 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4730 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4732 if(ent->flags & RENDER_EQUALIZE)
4734 // first fix up ambient lighting...
4735 if(r_equalize_entities_minambient.value > 0)
4737 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4740 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4741 if(fa < r_equalize_entities_minambient.value * fd)
4744 // fa'/fd' = minambient
4745 // fa'+0.25*fd' = fa+0.25*fd
4747 // fa' = fd' * minambient
4748 // fd'*(0.25+minambient) = fa+0.25*fd
4750 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4751 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4753 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4754 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
4755 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4756 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4761 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4763 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4764 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4768 // adjust brightness and saturation to target
4769 avg[0] = avg[1] = avg[2] = fa / f;
4770 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4771 avg[0] = avg[1] = avg[2] = fd / f;
4772 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4778 VectorSet(ent->modellight_ambient, 1, 1, 1);
4780 // move the light direction into modelspace coordinates for lighting code
4781 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4782 if(VectorLength2(ent->modellight_lightdir) == 0)
4783 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4784 VectorNormalize(ent->modellight_lightdir);
4788 #define MAX_LINEOFSIGHTTRACES 64
4790 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4793 vec3_t boxmins, boxmaxs;
4796 dp_model_t *model = r_refdef.scene.worldmodel;
4798 if (!model || !model->brush.TraceLineOfSight)
4801 // expand the box a little
4802 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4803 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4804 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4805 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4806 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4807 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4809 // return true if eye is inside enlarged box
4810 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4814 VectorCopy(eye, start);
4815 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4816 if (model->brush.TraceLineOfSight(model, start, end))
4819 // try various random positions
4820 for (i = 0;i < numsamples;i++)
4822 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4823 if (model->brush.TraceLineOfSight(model, start, end))
4831 static void R_View_UpdateEntityVisible (void)
4836 entity_render_t *ent;
4838 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4839 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4840 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
4841 : RENDER_EXTERIORMODEL;
4842 if (!r_drawviewmodel.integer)
4843 renderimask |= RENDER_VIEWMODEL;
4844 if (!r_drawexteriormodel.integer)
4845 renderimask |= RENDER_EXTERIORMODEL;
4846 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4848 // worldmodel can check visibility
4849 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4850 for (i = 0;i < r_refdef.scene.numentities;i++)
4852 ent = r_refdef.scene.entities[i];
4853 if (!(ent->flags & renderimask))
4854 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)))
4855 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))
4856 r_refdef.viewcache.entityvisible[i] = true;
4858 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4859 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4861 for (i = 0;i < r_refdef.scene.numentities;i++)
4863 ent = r_refdef.scene.entities[i];
4864 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4866 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4868 continue; // temp entities do pvs only
4869 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4870 ent->last_trace_visibility = realtime;
4871 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4872 r_refdef.viewcache.entityvisible[i] = 0;
4879 // no worldmodel or it can't check visibility
4880 for (i = 0;i < r_refdef.scene.numentities;i++)
4882 ent = r_refdef.scene.entities[i];
4883 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));
4888 /// only used if skyrendermasked, and normally returns false
4889 int R_DrawBrushModelsSky (void)
4892 entity_render_t *ent;
4895 for (i = 0;i < r_refdef.scene.numentities;i++)
4897 if (!r_refdef.viewcache.entityvisible[i])
4899 ent = r_refdef.scene.entities[i];
4900 if (!ent->model || !ent->model->DrawSky)
4902 ent->model->DrawSky(ent);
4908 static void R_DrawNoModel(entity_render_t *ent);
4909 static void R_DrawModels(void)
4912 entity_render_t *ent;
4914 for (i = 0;i < r_refdef.scene.numentities;i++)
4916 if (!r_refdef.viewcache.entityvisible[i])
4918 ent = r_refdef.scene.entities[i];
4919 r_refdef.stats.entities++;
4920 if (ent->model && ent->model->Draw != NULL)
4921 ent->model->Draw(ent);
4927 static void R_DrawModelsDepth(void)
4930 entity_render_t *ent;
4932 for (i = 0;i < r_refdef.scene.numentities;i++)
4934 if (!r_refdef.viewcache.entityvisible[i])
4936 ent = r_refdef.scene.entities[i];
4937 if (ent->model && ent->model->DrawDepth != NULL)
4938 ent->model->DrawDepth(ent);
4942 static void R_DrawModelsDebug(void)
4945 entity_render_t *ent;
4947 for (i = 0;i < r_refdef.scene.numentities;i++)
4949 if (!r_refdef.viewcache.entityvisible[i])
4951 ent = r_refdef.scene.entities[i];
4952 if (ent->model && ent->model->DrawDebug != NULL)
4953 ent->model->DrawDebug(ent);
4957 static void R_DrawModelsAddWaterPlanes(void)
4960 entity_render_t *ent;
4962 for (i = 0;i < r_refdef.scene.numentities;i++)
4964 if (!r_refdef.viewcache.entityvisible[i])
4966 ent = r_refdef.scene.entities[i];
4967 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4968 ent->model->DrawAddWaterPlanes(ent);
4972 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4974 if (r_hdr_irisadaptation.integer)
4978 vec3_t diffusenormal;
4983 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4984 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4985 brightness = max(0.0000001f, brightness);
4986 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4987 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4988 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4989 current = r_hdr_irisadaptation_value.value;
4991 current = min(current + adjust, goal);
4992 else if (current > goal)
4993 current = max(current - adjust, goal);
4994 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4995 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4997 else if (r_hdr_irisadaptation_value.value != 1.0f)
4998 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5001 static void R_View_SetFrustum(const int *scissor)
5004 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5005 vec3_t forward, left, up, origin, v;
5009 // flipped x coordinates (because x points left here)
5010 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5011 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5013 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5014 switch(vid.renderpath)
5016 case RENDERPATH_D3D9:
5017 case RENDERPATH_D3D10:
5018 case RENDERPATH_D3D11:
5019 case RENDERPATH_SOFT:
5020 // non-flipped y coordinates
5021 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5022 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5024 case RENDERPATH_GL11:
5025 case RENDERPATH_GL13:
5026 case RENDERPATH_GL20:
5027 case RENDERPATH_GLES2:
5028 // non-flipped y coordinates
5029 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5030 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5035 // we can't trust r_refdef.view.forward and friends in reflected scenes
5036 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5039 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5040 r_refdef.view.frustum[0].normal[1] = 0 - 0;
5041 r_refdef.view.frustum[0].normal[2] = -1 - 0;
5042 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5043 r_refdef.view.frustum[1].normal[1] = 0 + 0;
5044 r_refdef.view.frustum[1].normal[2] = -1 + 0;
5045 r_refdef.view.frustum[2].normal[0] = 0 - 0;
5046 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5047 r_refdef.view.frustum[2].normal[2] = -1 - 0;
5048 r_refdef.view.frustum[3].normal[0] = 0 + 0;
5049 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5050 r_refdef.view.frustum[3].normal[2] = -1 + 0;
5054 zNear = r_refdef.nearclip;
5055 nudge = 1.0 - 1.0 / (1<<23);
5056 r_refdef.view.frustum[4].normal[0] = 0 - 0;
5057 r_refdef.view.frustum[4].normal[1] = 0 - 0;
5058 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5059 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5060 r_refdef.view.frustum[5].normal[0] = 0 + 0;
5061 r_refdef.view.frustum[5].normal[1] = 0 + 0;
5062 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5063 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5069 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5070 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5071 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5072 r_refdef.view.frustum[0].dist = m[15] - m[12];
5074 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5075 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5076 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5077 r_refdef.view.frustum[1].dist = m[15] + m[12];
5079 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5080 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5081 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5082 r_refdef.view.frustum[2].dist = m[15] - m[13];
5084 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5085 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5086 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5087 r_refdef.view.frustum[3].dist = m[15] + m[13];
5089 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5090 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5091 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5092 r_refdef.view.frustum[4].dist = m[15] - m[14];
5094 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5095 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5096 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5097 r_refdef.view.frustum[5].dist = m[15] + m[14];
5100 if (r_refdef.view.useperspective)
5102 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5103 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]);
5104 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]);
5105 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]);
5106 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]);
5108 // then the normals from the corners relative to origin
5109 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5110 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5111 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5112 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5114 // in a NORMAL view, forward cross left == up
5115 // in a REFLECTED view, forward cross left == down
5116 // so our cross products above need to be adjusted for a left handed coordinate system
5117 CrossProduct(forward, left, v);
5118 if(DotProduct(v, up) < 0)
5120 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5121 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5122 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5123 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5126 // Leaving those out was a mistake, those were in the old code, and they
5127 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5128 // I couldn't reproduce it after adding those normalizations. --blub
5129 VectorNormalize(r_refdef.view.frustum[0].normal);
5130 VectorNormalize(r_refdef.view.frustum[1].normal);
5131 VectorNormalize(r_refdef.view.frustum[2].normal);
5132 VectorNormalize(r_refdef.view.frustum[3].normal);
5134 // make the corners absolute
5135 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5136 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5137 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5138 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5141 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5143 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5144 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5145 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5146 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5147 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5151 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5152 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5153 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5154 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5155 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5156 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5157 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5158 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5159 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5160 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5162 r_refdef.view.numfrustumplanes = 5;
5164 if (r_refdef.view.useclipplane)
5166 r_refdef.view.numfrustumplanes = 6;
5167 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5170 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5171 PlaneClassify(r_refdef.view.frustum + i);
5173 // LordHavoc: note to all quake engine coders, Quake had a special case
5174 // for 90 degrees which assumed a square view (wrong), so I removed it,
5175 // Quake2 has it disabled as well.
5177 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5178 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5179 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5180 //PlaneClassify(&frustum[0]);
5182 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5183 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5184 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5185 //PlaneClassify(&frustum[1]);
5187 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5188 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5189 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5190 //PlaneClassify(&frustum[2]);
5192 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5193 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5194 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5195 //PlaneClassify(&frustum[3]);
5198 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5199 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5200 //PlaneClassify(&frustum[4]);
5203 void R_View_UpdateWithScissor(const int *myscissor)
5205 R_Main_ResizeViewCache();
5206 R_View_SetFrustum(myscissor);
5207 R_View_WorldVisibility(r_refdef.view.useclipplane);
5208 R_View_UpdateEntityVisible();
5209 R_View_UpdateEntityLighting();
5212 void R_View_Update(void)
5214 R_Main_ResizeViewCache();
5215 R_View_SetFrustum(NULL);
5216 R_View_WorldVisibility(r_refdef.view.useclipplane);
5217 R_View_UpdateEntityVisible();
5218 R_View_UpdateEntityLighting();
5221 void R_SetupView(qboolean allowwaterclippingplane)
5223 const float *customclipplane = NULL;
5225 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5227 // LordHavoc: couldn't figure out how to make this approach the
5228 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5229 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5230 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5231 dist = r_refdef.view.clipplane.dist;
5232 plane[0] = r_refdef.view.clipplane.normal[0];
5233 plane[1] = r_refdef.view.clipplane.normal[1];
5234 plane[2] = r_refdef.view.clipplane.normal[2];
5236 customclipplane = plane;
5239 if (!r_refdef.view.useperspective)
5240 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);
5241 else if (vid.stencil && r_useinfinitefarclip.integer)
5242 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);
5244 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);
5245 R_SetViewport(&r_refdef.view.viewport);
5248 void R_EntityMatrix(const matrix4x4_t *matrix)
5250 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5252 gl_modelmatrixchanged = false;
5253 gl_modelmatrix = *matrix;
5254 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5255 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5256 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5257 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5259 switch(vid.renderpath)
5261 case RENDERPATH_D3D9:
5263 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5264 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5267 case RENDERPATH_D3D10:
5268 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5270 case RENDERPATH_D3D11:
5271 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5273 case RENDERPATH_GL13:
5274 case RENDERPATH_GL11:
5275 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5277 case RENDERPATH_SOFT:
5278 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5279 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5281 case RENDERPATH_GL20:
5282 case RENDERPATH_GLES2:
5283 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5284 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5290 void R_ResetViewRendering2D(void)
5292 r_viewport_t viewport;
5295 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5296 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);
5297 R_SetViewport(&viewport);
5298 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5299 GL_Color(1, 1, 1, 1);
5300 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5301 GL_BlendFunc(GL_ONE, GL_ZERO);
5302 GL_ScissorTest(false);
5303 GL_DepthMask(false);
5304 GL_DepthRange(0, 1);
5305 GL_DepthTest(false);
5306 GL_DepthFunc(GL_LEQUAL);
5307 R_EntityMatrix(&identitymatrix);
5308 R_Mesh_ResetTextureState();
5309 GL_PolygonOffset(0, 0);
5310 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5311 switch(vid.renderpath)
5313 case RENDERPATH_GL11:
5314 case RENDERPATH_GL13:
5315 case RENDERPATH_GL20:
5316 case RENDERPATH_GLES2:
5317 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5319 case RENDERPATH_D3D9:
5320 case RENDERPATH_D3D10:
5321 case RENDERPATH_D3D11:
5322 case RENDERPATH_SOFT:
5325 GL_CullFace(GL_NONE);
5328 void R_ResetViewRendering3D(void)
5333 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5334 GL_Color(1, 1, 1, 1);
5335 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5336 GL_BlendFunc(GL_ONE, GL_ZERO);
5337 GL_ScissorTest(true);
5339 GL_DepthRange(0, 1);
5341 GL_DepthFunc(GL_LEQUAL);
5342 R_EntityMatrix(&identitymatrix);
5343 R_Mesh_ResetTextureState();
5344 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5345 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5346 switch(vid.renderpath)
5348 case RENDERPATH_GL11:
5349 case RENDERPATH_GL13:
5350 case RENDERPATH_GL20:
5351 case RENDERPATH_GLES2:
5352 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5354 case RENDERPATH_D3D9:
5355 case RENDERPATH_D3D10:
5356 case RENDERPATH_D3D11:
5357 case RENDERPATH_SOFT:
5360 GL_CullFace(r_refdef.view.cullface_back);
5365 R_RenderView_UpdateViewVectors
5368 static void R_RenderView_UpdateViewVectors(void)
5370 // break apart the view matrix into vectors for various purposes
5371 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5372 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5373 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5374 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5375 // make an inverted copy of the view matrix for tracking sprites
5376 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5379 void R_RenderScene(void);
5380 void R_RenderWaterPlanes(void);
5382 static void R_Water_StartFrame(void)
5385 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5386 r_waterstate_waterplane_t *p;
5388 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5391 switch(vid.renderpath)
5393 case RENDERPATH_GL20:
5394 case RENDERPATH_D3D9:
5395 case RENDERPATH_D3D10:
5396 case RENDERPATH_D3D11:
5397 case RENDERPATH_SOFT:
5398 case RENDERPATH_GLES2:
5400 case RENDERPATH_GL13:
5401 case RENDERPATH_GL11:
5405 // set waterwidth and waterheight to the water resolution that will be
5406 // used (often less than the screen resolution for faster rendering)
5407 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5408 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5410 // calculate desired texture sizes
5411 // can't use water if the card does not support the texture size
5412 if (!r_water.integer || r_showsurfaces.integer)
5413 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5414 else if (vid.support.arb_texture_non_power_of_two)
5416 texturewidth = waterwidth;
5417 textureheight = waterheight;
5418 camerawidth = waterwidth;
5419 cameraheight = waterheight;
5423 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5424 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5425 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5426 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5429 // allocate textures as needed
5430 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5432 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5433 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5435 if (p->texture_refraction)
5436 R_FreeTexture(p->texture_refraction);
5437 p->texture_refraction = NULL;
5438 if (p->texture_reflection)
5439 R_FreeTexture(p->texture_reflection);
5440 p->texture_reflection = NULL;
5441 if (p->texture_camera)
5442 R_FreeTexture(p->texture_camera);
5443 p->texture_camera = NULL;
5445 memset(&r_waterstate, 0, sizeof(r_waterstate));
5446 r_waterstate.texturewidth = texturewidth;
5447 r_waterstate.textureheight = textureheight;
5448 r_waterstate.camerawidth = camerawidth;
5449 r_waterstate.cameraheight = cameraheight;
5452 if (r_waterstate.texturewidth)
5454 r_waterstate.enabled = true;
5456 // when doing a reduced render (HDR) we want to use a smaller area
5457 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5458 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5460 // set up variables that will be used in shader setup
5461 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5462 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5463 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5464 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5467 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5468 r_waterstate.numwaterplanes = 0;
5471 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5473 int triangleindex, planeindex;
5479 r_waterstate_waterplane_t *p;
5480 texture_t *t = R_GetCurrentTexture(surface->texture);
5482 // just use the first triangle with a valid normal for any decisions
5483 VectorClear(normal);
5484 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5486 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5487 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5488 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5489 TriangleNormal(vert[0], vert[1], vert[2], normal);
5490 if (VectorLength2(normal) >= 0.001)
5494 VectorCopy(normal, plane.normal);
5495 VectorNormalize(plane.normal);
5496 plane.dist = DotProduct(vert[0], plane.normal);
5497 PlaneClassify(&plane);
5498 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5500 // skip backfaces (except if nocullface is set)
5501 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5503 VectorNegate(plane.normal, plane.normal);
5505 PlaneClassify(&plane);
5509 // find a matching plane if there is one
5510 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5511 if(p->camera_entity == t->camera_entity)
5512 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5514 if (planeindex >= r_waterstate.maxwaterplanes)
5515 return; // nothing we can do, out of planes
5517 // if this triangle does not fit any known plane rendered this frame, add one
5518 if (planeindex >= r_waterstate.numwaterplanes)
5520 // store the new plane
5521 r_waterstate.numwaterplanes++;
5523 // clear materialflags and pvs
5524 p->materialflags = 0;
5525 p->pvsvalid = false;
5526 p->camera_entity = t->camera_entity;
5527 VectorCopy(surface->mins, p->mins);
5528 VectorCopy(surface->maxs, p->maxs);
5533 p->mins[0] = min(p->mins[0], surface->mins[0]);
5534 p->mins[1] = min(p->mins[1], surface->mins[1]);
5535 p->mins[2] = min(p->mins[2], surface->mins[2]);
5536 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5537 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5538 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5540 // merge this surface's materialflags into the waterplane
5541 p->materialflags |= t->currentmaterialflags;
5542 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5544 // merge this surface's PVS into the waterplane
5545 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5546 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5547 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5549 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5555 static void R_Water_ProcessPlanes(void)
5558 r_refdef_view_t originalview;
5559 r_refdef_view_t myview;
5561 r_waterstate_waterplane_t *p;
5564 originalview = r_refdef.view;
5566 // make sure enough textures are allocated
5567 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5569 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5571 if (!p->texture_refraction)
5572 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);
5573 if (!p->texture_refraction)
5576 else if (p->materialflags & MATERIALFLAG_CAMERA)
5578 if (!p->texture_camera)
5579 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);
5580 if (!p->texture_camera)
5584 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5586 if (!p->texture_reflection)
5587 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);
5588 if (!p->texture_reflection)
5594 r_refdef.view = originalview;
5595 r_refdef.view.showdebug = false;
5596 r_refdef.view.width = r_waterstate.waterwidth;
5597 r_refdef.view.height = r_waterstate.waterheight;
5598 r_refdef.view.useclipplane = true;
5599 myview = r_refdef.view;
5600 r_waterstate.renderingscene = true;
5601 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5603 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5605 r_refdef.view = myview;
5606 if(r_water_scissormode.integer)
5609 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5610 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5613 // render reflected scene and copy into texture
5614 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5615 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5616 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5617 r_refdef.view.clipplane = p->plane;
5619 // reverse the cullface settings for this render
5620 r_refdef.view.cullface_front = GL_FRONT;
5621 r_refdef.view.cullface_back = GL_BACK;
5622 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5624 r_refdef.view.usecustompvs = true;
5626 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5628 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5631 R_ResetViewRendering3D();
5632 R_ClearScreen(r_refdef.fogenabled);
5633 if(r_water_scissormode.integer & 2)
5634 R_View_UpdateWithScissor(myscissor);
5637 if(r_water_scissormode.integer & 1)
5638 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5641 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);
5644 // render the normal view scene and copy into texture
5645 // (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)
5646 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5648 r_refdef.view = myview;
5649 if(r_water_scissormode.integer)
5652 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5653 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5656 r_waterstate.renderingrefraction = true;
5658 r_refdef.view.clipplane = p->plane;
5659 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5660 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5662 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5664 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5665 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5666 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5667 R_RenderView_UpdateViewVectors();
5668 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5670 r_refdef.view.usecustompvs = true;
5671 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);
5675 PlaneClassify(&r_refdef.view.clipplane);
5677 R_ResetViewRendering3D();
5678 R_ClearScreen(r_refdef.fogenabled);
5679 if(r_water_scissormode.integer & 2)
5680 R_View_UpdateWithScissor(myscissor);
5683 if(r_water_scissormode.integer & 1)
5684 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5687 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);
5688 r_waterstate.renderingrefraction = false;
5690 else if (p->materialflags & MATERIALFLAG_CAMERA)
5692 r_refdef.view = myview;
5694 r_refdef.view.clipplane = p->plane;
5695 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5696 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5698 r_refdef.view.width = r_waterstate.camerawidth;
5699 r_refdef.view.height = r_waterstate.cameraheight;
5700 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5701 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5703 if(p->camera_entity)
5705 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5706 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5709 // note: all of the view is used for displaying... so
5710 // there is no use in scissoring
5712 // reverse the cullface settings for this render
5713 r_refdef.view.cullface_front = GL_FRONT;
5714 r_refdef.view.cullface_back = GL_BACK;
5715 // also reverse the view matrix
5716 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
5717 R_RenderView_UpdateViewVectors();
5718 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5720 r_refdef.view.usecustompvs = true;
5721 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);
5724 // camera needs no clipplane
5725 r_refdef.view.useclipplane = false;
5727 PlaneClassify(&r_refdef.view.clipplane);
5729 R_ResetViewRendering3D();
5730 R_ClearScreen(r_refdef.fogenabled);
5734 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);
5735 r_waterstate.renderingrefraction = false;
5739 r_waterstate.renderingscene = false;
5740 r_refdef.view = originalview;
5741 R_ResetViewRendering3D();
5742 R_ClearScreen(r_refdef.fogenabled);
5746 r_refdef.view = originalview;
5747 r_waterstate.renderingscene = false;
5748 Cvar_SetValueQuick(&r_water, 0);
5749 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5753 void R_Bloom_StartFrame(void)
5755 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5757 switch(vid.renderpath)
5759 case RENDERPATH_GL20:
5760 case RENDERPATH_D3D9:
5761 case RENDERPATH_D3D10:
5762 case RENDERPATH_D3D11:
5763 case RENDERPATH_SOFT:
5764 case RENDERPATH_GLES2:
5766 case RENDERPATH_GL13:
5767 case RENDERPATH_GL11:
5771 // set bloomwidth and bloomheight to the bloom resolution that will be
5772 // used (often less than the screen resolution for faster rendering)
5773 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5774 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5775 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5776 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5777 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5779 // calculate desired texture sizes
5780 if (vid.support.arb_texture_non_power_of_two)
5782 screentexturewidth = r_refdef.view.width;
5783 screentextureheight = r_refdef.view.height;
5784 bloomtexturewidth = r_bloomstate.bloomwidth;
5785 bloomtextureheight = r_bloomstate.bloomheight;
5789 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
5790 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
5791 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
5792 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
5795 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))
5797 Cvar_SetValueQuick(&r_hdr, 0);
5798 Cvar_SetValueQuick(&r_bloom, 0);
5799 Cvar_SetValueQuick(&r_motionblur, 0);
5800 Cvar_SetValueQuick(&r_damageblur, 0);
5803 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)))
5804 screentexturewidth = screentextureheight = 0;
5805 if (!r_hdr.integer && !r_bloom.integer)
5806 bloomtexturewidth = bloomtextureheight = 0;
5808 // allocate textures as needed
5809 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
5811 if (r_bloomstate.texture_screen)
5812 R_FreeTexture(r_bloomstate.texture_screen);
5813 r_bloomstate.texture_screen = NULL;
5814 r_bloomstate.screentexturewidth = screentexturewidth;
5815 r_bloomstate.screentextureheight = screentextureheight;
5816 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5817 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);
5819 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
5821 if (r_bloomstate.texture_bloom)
5822 R_FreeTexture(r_bloomstate.texture_bloom);
5823 r_bloomstate.texture_bloom = NULL;
5824 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5825 r_bloomstate.bloomtextureheight = bloomtextureheight;
5826 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5827 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);
5830 // when doing a reduced render (HDR) we want to use a smaller area
5831 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5832 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5833 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5834 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5835 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5837 // set up a texcoord array for the full resolution screen image
5838 // (we have to keep this around to copy back during final render)
5839 r_bloomstate.screentexcoord2f[0] = 0;
5840 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
5841 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
5842 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
5843 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
5844 r_bloomstate.screentexcoord2f[5] = 0;
5845 r_bloomstate.screentexcoord2f[6] = 0;
5846 r_bloomstate.screentexcoord2f[7] = 0;
5848 // set up a texcoord array for the reduced resolution bloom image
5849 // (which will be additive blended over the screen image)
5850 r_bloomstate.bloomtexcoord2f[0] = 0;
5851 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5852 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5853 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5854 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5855 r_bloomstate.bloomtexcoord2f[5] = 0;
5856 r_bloomstate.bloomtexcoord2f[6] = 0;
5857 r_bloomstate.bloomtexcoord2f[7] = 0;
5859 switch(vid.renderpath)
5861 case RENDERPATH_GL11:
5862 case RENDERPATH_GL13:
5863 case RENDERPATH_GL20:
5864 case RENDERPATH_SOFT:
5865 case RENDERPATH_GLES2:
5867 case RENDERPATH_D3D9:
5868 case RENDERPATH_D3D10:
5869 case RENDERPATH_D3D11:
5872 for (i = 0;i < 4;i++)
5874 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5875 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5876 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5877 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5883 if (r_hdr.integer || r_bloom.integer)
5885 r_bloomstate.enabled = true;
5886 r_bloomstate.hdr = r_hdr.integer != 0;
5889 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);
5892 void R_Bloom_CopyBloomTexture(float colorscale)
5894 r_refdef.stats.bloom++;
5896 // scale down screen texture to the bloom texture size
5898 R_SetViewport(&r_bloomstate.viewport);
5899 GL_BlendFunc(GL_ONE, GL_ZERO);
5900 GL_Color(colorscale, colorscale, colorscale, 1);
5901 // 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...
5902 switch(vid.renderpath)
5904 case RENDERPATH_GL11:
5905 case RENDERPATH_GL13:
5906 case RENDERPATH_GL20:
5907 case RENDERPATH_SOFT:
5908 case RENDERPATH_GLES2:
5909 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5911 case RENDERPATH_D3D9:
5912 case RENDERPATH_D3D10:
5913 case RENDERPATH_D3D11:
5914 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5917 // TODO: do boxfilter scale-down in shader?
5918 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5919 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5920 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5922 // we now have a bloom image in the framebuffer
5923 // copy it into the bloom image texture for later processing
5924 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);
5925 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5928 void R_Bloom_CopyHDRTexture(void)
5930 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);
5931 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5934 void R_Bloom_MakeTexture(void)
5937 float xoffset, yoffset, r, brighten;
5939 r_refdef.stats.bloom++;
5941 R_ResetViewRendering2D();
5943 // we have a bloom image in the framebuffer
5945 R_SetViewport(&r_bloomstate.viewport);
5947 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5950 r = bound(0, r_bloom_colorexponent.value / x, 1);
5951 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5953 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5954 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5955 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5956 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5958 // copy the vertically blurred bloom view to a texture
5959 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);
5960 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5963 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5964 brighten = r_bloom_brighten.value;
5966 brighten *= r_hdr_range.value;
5967 brighten = sqrt(brighten);
5969 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5970 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5972 for (dir = 0;dir < 2;dir++)
5974 // blend on at multiple vertical offsets to achieve a vertical blur
5975 // TODO: do offset blends using GLSL
5976 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5977 GL_BlendFunc(GL_ONE, GL_ZERO);
5978 for (x = -range;x <= range;x++)
5980 if (!dir){xoffset = 0;yoffset = x;}
5981 else {xoffset = x;yoffset = 0;}
5982 xoffset /= (float)r_bloomstate.bloomtexturewidth;
5983 yoffset /= (float)r_bloomstate.bloomtextureheight;
5984 // compute a texcoord array with the specified x and y offset
5985 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
5986 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5987 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5988 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5989 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5990 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
5991 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
5992 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
5993 // this r value looks like a 'dot' particle, fading sharply to
5994 // black at the edges
5995 // (probably not realistic but looks good enough)
5996 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
5997 //r = brighten/(range*2+1);
5998 r = brighten / (range * 2 + 1);
6000 r *= (1 - x*x/(float)(range*range));
6001 GL_Color(r, r, r, 1);
6002 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6003 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6004 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6005 GL_BlendFunc(GL_ONE, GL_ONE);
6008 // copy the vertically blurred bloom view to a texture
6009 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);
6010 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6014 void R_HDR_RenderBloomTexture(void)
6016 int oldwidth, oldheight;
6017 float oldcolorscale;
6018 qboolean oldwaterstate;
6020 oldwaterstate = r_waterstate.enabled;
6021 oldcolorscale = r_refdef.view.colorscale;
6022 oldwidth = r_refdef.view.width;
6023 oldheight = r_refdef.view.height;
6024 r_refdef.view.width = r_bloomstate.bloomwidth;
6025 r_refdef.view.height = r_bloomstate.bloomheight;
6027 if(r_hdr.integer < 2)
6028 r_waterstate.enabled = false;
6030 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
6031 // TODO: add exposure compensation features
6032 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6034 r_refdef.view.showdebug = false;
6035 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6037 R_ResetViewRendering3D();
6039 R_ClearScreen(r_refdef.fogenabled);
6040 if (r_timereport_active)
6041 R_TimeReport("HDRclear");
6044 if (r_timereport_active)
6045 R_TimeReport("visibility");
6047 // only do secondary renders with HDR if r_hdr is 2 or higher
6048 r_waterstate.numwaterplanes = 0;
6049 if (r_waterstate.enabled)
6050 R_RenderWaterPlanes();
6052 r_refdef.view.showdebug = true;
6054 r_waterstate.numwaterplanes = 0;
6056 R_ResetViewRendering2D();
6058 R_Bloom_CopyHDRTexture();
6059 R_Bloom_MakeTexture();
6061 // restore the view settings
6062 r_waterstate.enabled = oldwaterstate;
6063 r_refdef.view.width = oldwidth;
6064 r_refdef.view.height = oldheight;
6065 r_refdef.view.colorscale = oldcolorscale;
6067 R_ResetViewRendering3D();
6069 R_ClearScreen(r_refdef.fogenabled);
6070 if (r_timereport_active)
6071 R_TimeReport("viewclear");
6074 static void R_BlendView(void)
6076 unsigned int permutation;
6077 float uservecs[4][4];
6079 switch (vid.renderpath)
6081 case RENDERPATH_GL20:
6082 case RENDERPATH_D3D9:
6083 case RENDERPATH_D3D10:
6084 case RENDERPATH_D3D11:
6085 case RENDERPATH_SOFT:
6086 case RENDERPATH_GLES2:
6088 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6089 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6090 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6091 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6092 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6094 if (r_bloomstate.texture_screen)
6096 // make sure the buffer is available
6097 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6099 R_ResetViewRendering2D();
6101 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6103 // declare variables
6105 static float avgspeed;
6107 speed = VectorLength(cl.movement_velocity);
6109 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6110 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6112 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6113 speed = bound(0, speed, 1);
6114 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6116 // calculate values into a standard alpha
6117 cl.motionbluralpha = 1 - exp(-
6119 (r_motionblur.value * speed / 80)
6121 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6124 max(0.0001, cl.time - cl.oldtime) // fps independent
6127 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6128 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6130 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6132 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6133 GL_Color(1, 1, 1, cl.motionbluralpha);
6134 switch(vid.renderpath)
6136 case RENDERPATH_GL11:
6137 case RENDERPATH_GL13:
6138 case RENDERPATH_GL20:
6139 case RENDERPATH_SOFT:
6140 case RENDERPATH_GLES2:
6141 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6143 case RENDERPATH_D3D9:
6144 case RENDERPATH_D3D10:
6145 case RENDERPATH_D3D11:
6146 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6149 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6150 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6151 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6155 // copy view into the screen texture
6156 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);
6157 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6159 else if (!r_bloomstate.texture_bloom)
6161 // we may still have to do view tint...
6162 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6164 // apply a color tint to the whole view
6165 R_ResetViewRendering2D();
6166 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6167 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6168 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6169 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6170 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6172 break; // no screen processing, no bloom, skip it
6175 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6177 // render simple bloom effect
6178 // copy the screen and shrink it and darken it for the bloom process
6179 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6180 // make the bloom texture
6181 R_Bloom_MakeTexture();
6184 #if _MSC_VER >= 1400
6185 #define sscanf sscanf_s
6187 memset(uservecs, 0, sizeof(uservecs));
6188 if (r_glsl_postprocess_uservec1_enable.integer)
6189 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6190 if (r_glsl_postprocess_uservec2_enable.integer)
6191 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6192 if (r_glsl_postprocess_uservec3_enable.integer)
6193 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6194 if (r_glsl_postprocess_uservec4_enable.integer)
6195 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6197 R_ResetViewRendering2D();
6198 GL_Color(1, 1, 1, 1);
6199 GL_BlendFunc(GL_ONE, GL_ZERO);
6201 switch(vid.renderpath)
6203 case RENDERPATH_GL20:
6204 case RENDERPATH_GLES2:
6205 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6206 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6207 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6208 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6209 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6210 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]);
6211 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6212 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]);
6213 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]);
6214 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]);
6215 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]);
6216 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6217 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6218 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);
6220 case RENDERPATH_D3D9:
6222 // 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...
6223 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6224 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6225 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6226 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6227 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6228 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6229 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6230 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6231 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6232 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6233 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6234 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6235 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6236 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6239 case RENDERPATH_D3D10:
6240 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6242 case RENDERPATH_D3D11:
6243 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6245 case RENDERPATH_SOFT:
6246 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6247 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6248 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6249 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6250 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6251 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6252 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6253 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6254 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6255 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6256 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6257 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6258 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6259 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6264 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6265 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6267 case RENDERPATH_GL13:
6268 case RENDERPATH_GL11:
6269 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6271 // apply a color tint to the whole view
6272 R_ResetViewRendering2D();
6273 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6274 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6275 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6276 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6277 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6283 matrix4x4_t r_waterscrollmatrix;
6285 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6287 if (r_refdef.fog_density)
6289 r_refdef.fogcolor[0] = r_refdef.fog_red;
6290 r_refdef.fogcolor[1] = r_refdef.fog_green;
6291 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6293 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6294 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6295 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6296 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6300 VectorCopy(r_refdef.fogcolor, fogvec);
6301 // color.rgb *= ContrastBoost * SceneBrightness;
6302 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6303 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6304 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6305 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6310 void R_UpdateVariables(void)
6314 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6316 r_refdef.farclip = r_farclip_base.value;
6317 if (r_refdef.scene.worldmodel)
6318 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6319 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6321 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6322 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6323 r_refdef.polygonfactor = 0;
6324 r_refdef.polygonoffset = 0;
6325 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6326 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6328 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6329 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6330 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6331 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6332 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6333 if (FAKELIGHT_ENABLED)
6335 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6337 if (r_showsurfaces.integer)
6339 r_refdef.scene.rtworld = false;
6340 r_refdef.scene.rtworldshadows = false;
6341 r_refdef.scene.rtdlight = false;
6342 r_refdef.scene.rtdlightshadows = false;
6343 r_refdef.lightmapintensity = 0;
6346 if (gamemode == GAME_NEHAHRA)
6348 if (gl_fogenable.integer)
6350 r_refdef.oldgl_fogenable = true;
6351 r_refdef.fog_density = gl_fogdensity.value;
6352 r_refdef.fog_red = gl_fogred.value;
6353 r_refdef.fog_green = gl_foggreen.value;
6354 r_refdef.fog_blue = gl_fogblue.value;
6355 r_refdef.fog_alpha = 1;
6356 r_refdef.fog_start = 0;
6357 r_refdef.fog_end = gl_skyclip.value;
6358 r_refdef.fog_height = 1<<30;
6359 r_refdef.fog_fadedepth = 128;
6361 else if (r_refdef.oldgl_fogenable)
6363 r_refdef.oldgl_fogenable = false;
6364 r_refdef.fog_density = 0;
6365 r_refdef.fog_red = 0;
6366 r_refdef.fog_green = 0;
6367 r_refdef.fog_blue = 0;
6368 r_refdef.fog_alpha = 0;
6369 r_refdef.fog_start = 0;
6370 r_refdef.fog_end = 0;
6371 r_refdef.fog_height = 1<<30;
6372 r_refdef.fog_fadedepth = 128;
6376 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6377 r_refdef.fog_start = max(0, r_refdef.fog_start);
6378 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6380 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6382 if (r_refdef.fog_density && r_drawfog.integer)
6384 r_refdef.fogenabled = true;
6385 // this is the point where the fog reaches 0.9986 alpha, which we
6386 // consider a good enough cutoff point for the texture
6387 // (0.9986 * 256 == 255.6)
6388 if (r_fog_exp2.integer)
6389 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6391 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6392 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6393 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6394 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6395 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6396 R_BuildFogHeightTexture();
6397 // fog color was already set
6398 // update the fog texture
6399 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)
6400 R_BuildFogTexture();
6401 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6402 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6405 r_refdef.fogenabled = false;
6407 switch(vid.renderpath)
6409 case RENDERPATH_GL20:
6410 case RENDERPATH_D3D9:
6411 case RENDERPATH_D3D10:
6412 case RENDERPATH_D3D11:
6413 case RENDERPATH_SOFT:
6414 case RENDERPATH_GLES2:
6415 if(v_glslgamma.integer && !vid_gammatables_trivial)
6417 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6419 // build GLSL gamma texture
6420 #define RAMPWIDTH 256
6421 unsigned short ramp[RAMPWIDTH * 3];
6422 unsigned char rampbgr[RAMPWIDTH][4];
6425 r_texture_gammaramps_serial = vid_gammatables_serial;
6427 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6428 for(i = 0; i < RAMPWIDTH; ++i)
6430 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6431 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6432 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6435 if (r_texture_gammaramps)
6437 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6441 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6447 // remove GLSL gamma texture
6450 case RENDERPATH_GL13:
6451 case RENDERPATH_GL11:
6456 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6457 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6463 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6464 if( scenetype != r_currentscenetype ) {
6465 // store the old scenetype
6466 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6467 r_currentscenetype = scenetype;
6468 // move in the new scene
6469 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6478 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6480 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6481 if( scenetype == r_currentscenetype ) {
6482 return &r_refdef.scene;
6484 return &r_scenes_store[ scenetype ];
6493 int dpsoftrast_test;
6494 void R_RenderView(void)
6496 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6498 dpsoftrast_test = r_test.integer;
6500 if (r_timereport_active)
6501 R_TimeReport("start");
6502 r_textureframe++; // used only by R_GetCurrentTexture
6503 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6505 if(R_CompileShader_CheckStaticParms())
6508 if (!r_drawentities.integer)
6509 r_refdef.scene.numentities = 0;
6511 R_AnimCache_ClearCache();
6512 R_FrameData_NewFrame();
6514 /* adjust for stereo display */
6515 if(R_Stereo_Active())
6517 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);
6518 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6521 if (r_refdef.view.isoverlay)
6523 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6524 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6525 R_TimeReport("depthclear");
6527 r_refdef.view.showdebug = false;
6529 r_waterstate.enabled = false;
6530 r_waterstate.numwaterplanes = 0;
6534 r_refdef.view.matrix = originalmatrix;
6540 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6542 r_refdef.view.matrix = originalmatrix;
6543 return; //Host_Error ("R_RenderView: NULL worldmodel");
6546 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6548 R_RenderView_UpdateViewVectors();
6550 R_Shadow_UpdateWorldLightSelection();
6552 R_Bloom_StartFrame();
6553 R_Water_StartFrame();
6556 if (r_timereport_active)
6557 R_TimeReport("viewsetup");
6559 R_ResetViewRendering3D();
6561 if (r_refdef.view.clear || r_refdef.fogenabled)
6563 R_ClearScreen(r_refdef.fogenabled);
6564 if (r_timereport_active)
6565 R_TimeReport("viewclear");
6567 r_refdef.view.clear = true;
6569 // this produces a bloom texture to be used in R_BlendView() later
6570 if (r_hdr.integer && r_bloomstate.bloomwidth)
6572 R_HDR_RenderBloomTexture();
6573 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6574 r_textureframe++; // used only by R_GetCurrentTexture
6577 r_refdef.view.showdebug = true;
6580 if (r_timereport_active)
6581 R_TimeReport("visibility");
6583 r_waterstate.numwaterplanes = 0;
6584 if (r_waterstate.enabled)
6585 R_RenderWaterPlanes();
6588 r_waterstate.numwaterplanes = 0;
6591 if (r_timereport_active)
6592 R_TimeReport("blendview");
6594 GL_Scissor(0, 0, vid.width, vid.height);
6595 GL_ScissorTest(false);
6597 r_refdef.view.matrix = originalmatrix;
6602 void R_RenderWaterPlanes(void)
6604 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6606 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6607 if (r_timereport_active)
6608 R_TimeReport("waterworld");
6611 // don't let sound skip if going slow
6612 if (r_refdef.scene.extraupdate)
6615 R_DrawModelsAddWaterPlanes();
6616 if (r_timereport_active)
6617 R_TimeReport("watermodels");
6619 if (r_waterstate.numwaterplanes)
6621 R_Water_ProcessPlanes();
6622 if (r_timereport_active)
6623 R_TimeReport("waterscenes");
6627 extern void R_DrawLightningBeams (void);
6628 extern void VM_CL_AddPolygonsToMeshQueue (void);
6629 extern void R_DrawPortals (void);
6630 extern cvar_t cl_locs_show;
6631 static void R_DrawLocs(void);
6632 static void R_DrawEntityBBoxes(void);
6633 static void R_DrawModelDecals(void);
6634 extern void R_DrawModelShadows(void);
6635 extern void R_DrawModelShadowMaps(void);
6636 extern cvar_t cl_decals_newsystem;
6637 extern qboolean r_shadow_usingdeferredprepass;
6638 void R_RenderScene(void)
6640 qboolean shadowmapping = false;
6642 if (r_timereport_active)
6643 R_TimeReport("beginscene");
6645 r_refdef.stats.renders++;
6649 // don't let sound skip if going slow
6650 if (r_refdef.scene.extraupdate)
6653 R_MeshQueue_BeginScene();
6657 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);
6659 if (r_timereport_active)
6660 R_TimeReport("skystartframe");
6662 if (cl.csqc_vidvars.drawworld)
6664 // don't let sound skip if going slow
6665 if (r_refdef.scene.extraupdate)
6668 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6670 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6671 if (r_timereport_active)
6672 R_TimeReport("worldsky");
6675 if (R_DrawBrushModelsSky() && r_timereport_active)
6676 R_TimeReport("bmodelsky");
6678 if (skyrendermasked && skyrenderlater)
6680 // we have to force off the water clipping plane while rendering sky
6684 if (r_timereport_active)
6685 R_TimeReport("sky");
6689 R_AnimCache_CacheVisibleEntities();
6690 if (r_timereport_active)
6691 R_TimeReport("animation");
6693 R_Shadow_PrepareLights();
6694 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6695 R_Shadow_PrepareModelShadows();
6696 if (r_timereport_active)
6697 R_TimeReport("preparelights");
6699 if (R_Shadow_ShadowMappingEnabled())
6700 shadowmapping = true;
6702 if (r_shadow_usingdeferredprepass)
6703 R_Shadow_DrawPrepass();
6705 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6707 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6708 if (r_timereport_active)
6709 R_TimeReport("worlddepth");
6711 if (r_depthfirst.integer >= 2)
6713 R_DrawModelsDepth();
6714 if (r_timereport_active)
6715 R_TimeReport("modeldepth");
6718 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6720 R_DrawModelShadowMaps();
6721 R_ResetViewRendering3D();
6722 // don't let sound skip if going slow
6723 if (r_refdef.scene.extraupdate)
6727 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6729 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6730 if (r_timereport_active)
6731 R_TimeReport("world");
6734 // don't let sound skip if going slow
6735 if (r_refdef.scene.extraupdate)
6739 if (r_timereport_active)
6740 R_TimeReport("models");
6742 // don't let sound skip if going slow
6743 if (r_refdef.scene.extraupdate)
6746 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6748 R_DrawModelShadows();
6749 R_ResetViewRendering3D();
6750 // don't let sound skip if going slow
6751 if (r_refdef.scene.extraupdate)
6755 if (!r_shadow_usingdeferredprepass)
6757 R_Shadow_DrawLights();
6758 if (r_timereport_active)
6759 R_TimeReport("rtlights");
6762 // don't let sound skip if going slow
6763 if (r_refdef.scene.extraupdate)
6766 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6768 R_DrawModelShadows();
6769 R_ResetViewRendering3D();
6770 // don't let sound skip if going slow
6771 if (r_refdef.scene.extraupdate)
6775 if (cl.csqc_vidvars.drawworld)
6777 if (cl_decals_newsystem.integer)
6779 R_DrawModelDecals();
6780 if (r_timereport_active)
6781 R_TimeReport("modeldecals");
6786 if (r_timereport_active)
6787 R_TimeReport("decals");
6791 if (r_timereport_active)
6792 R_TimeReport("particles");
6795 if (r_timereport_active)
6796 R_TimeReport("explosions");
6798 R_DrawLightningBeams();
6799 if (r_timereport_active)
6800 R_TimeReport("lightning");
6803 VM_CL_AddPolygonsToMeshQueue();
6805 if (r_refdef.view.showdebug)
6807 if (cl_locs_show.integer)
6810 if (r_timereport_active)
6811 R_TimeReport("showlocs");
6814 if (r_drawportals.integer)
6817 if (r_timereport_active)
6818 R_TimeReport("portals");
6821 if (r_showbboxes.value > 0)
6823 R_DrawEntityBBoxes();
6824 if (r_timereport_active)
6825 R_TimeReport("bboxes");
6829 R_MeshQueue_RenderTransparent();
6830 if (r_timereport_active)
6831 R_TimeReport("drawtrans");
6833 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))
6835 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6836 if (r_timereport_active)
6837 R_TimeReport("worlddebug");
6838 R_DrawModelsDebug();
6839 if (r_timereport_active)
6840 R_TimeReport("modeldebug");
6843 if (cl.csqc_vidvars.drawworld)
6845 R_Shadow_DrawCoronas();
6846 if (r_timereport_active)
6847 R_TimeReport("coronas");
6852 GL_DepthTest(false);
6853 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6854 GL_Color(1, 1, 1, 1);
6855 qglBegin(GL_POLYGON);
6856 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6857 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6858 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6859 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6861 qglBegin(GL_POLYGON);
6862 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]);
6863 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]);
6864 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]);
6865 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]);
6867 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6871 // don't let sound skip if going slow
6872 if (r_refdef.scene.extraupdate)
6875 R_ResetViewRendering2D();
6878 static const unsigned short bboxelements[36] =
6888 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6891 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6893 RSurf_ActiveWorldEntity();
6895 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6896 GL_DepthMask(false);
6897 GL_DepthRange(0, 1);
6898 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6899 // R_Mesh_ResetTextureState();
6901 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6902 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6903 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6904 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6905 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6906 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6907 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6908 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6909 R_FillColors(color4f, 8, cr, cg, cb, ca);
6910 if (r_refdef.fogenabled)
6912 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6914 f1 = RSurf_FogVertex(v);
6916 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6917 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6918 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6921 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6922 R_Mesh_ResetTextureState();
6923 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6924 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6927 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6931 prvm_edict_t *edict;
6932 prvm_prog_t *prog_save = prog;
6934 // this function draws bounding boxes of server entities
6938 GL_CullFace(GL_NONE);
6939 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6943 for (i = 0;i < numsurfaces;i++)
6945 edict = PRVM_EDICT_NUM(surfacelist[i]);
6946 switch ((int)edict->fields.server->solid)
6948 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
6949 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
6950 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
6951 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6952 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
6953 default: Vector4Set(color, 0, 0, 0, 0.50);break;
6955 color[3] *= r_showbboxes.value;
6956 color[3] = bound(0, color[3], 1);
6957 GL_DepthTest(!r_showdisabledepthtest.integer);
6958 GL_CullFace(r_refdef.view.cullface_front);
6959 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6965 static void R_DrawEntityBBoxes(void)
6968 prvm_edict_t *edict;
6970 prvm_prog_t *prog_save = prog;
6972 // this function draws bounding boxes of server entities
6978 for (i = 0;i < prog->num_edicts;i++)
6980 edict = PRVM_EDICT_NUM(i);
6981 if (edict->priv.server->free)
6983 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6984 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
6986 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
6988 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
6989 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
6995 static const int nomodelelement3i[24] =
7007 static const unsigned short nomodelelement3s[24] =
7019 static const float nomodelvertex3f[6*3] =
7029 static const float nomodelcolor4f[6*4] =
7031 0.0f, 0.0f, 0.5f, 1.0f,
7032 0.0f, 0.0f, 0.5f, 1.0f,
7033 0.0f, 0.5f, 0.0f, 1.0f,
7034 0.0f, 0.5f, 0.0f, 1.0f,
7035 0.5f, 0.0f, 0.0f, 1.0f,
7036 0.5f, 0.0f, 0.0f, 1.0f
7039 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7045 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);
7047 // this is only called once per entity so numsurfaces is always 1, and
7048 // surfacelist is always {0}, so this code does not handle batches
7050 if (rsurface.ent_flags & RENDER_ADDITIVE)
7052 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7053 GL_DepthMask(false);
7055 else if (rsurface.colormod[3] < 1)
7057 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7058 GL_DepthMask(false);
7062 GL_BlendFunc(GL_ONE, GL_ZERO);
7065 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7066 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7067 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7068 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7069 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7070 for (i = 0, c = color4f;i < 6;i++, c += 4)
7072 c[0] *= rsurface.colormod[0];
7073 c[1] *= rsurface.colormod[1];
7074 c[2] *= rsurface.colormod[2];
7075 c[3] *= rsurface.colormod[3];
7077 if (r_refdef.fogenabled)
7079 for (i = 0, c = color4f;i < 6;i++, c += 4)
7081 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7083 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7084 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7085 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7088 // R_Mesh_ResetTextureState();
7089 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7090 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7091 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7094 void R_DrawNoModel(entity_render_t *ent)
7097 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7098 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7099 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7101 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7104 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7106 vec3_t right1, right2, diff, normal;
7108 VectorSubtract (org2, org1, normal);
7110 // calculate 'right' vector for start
7111 VectorSubtract (r_refdef.view.origin, org1, diff);
7112 CrossProduct (normal, diff, right1);
7113 VectorNormalize (right1);
7115 // calculate 'right' vector for end
7116 VectorSubtract (r_refdef.view.origin, org2, diff);
7117 CrossProduct (normal, diff, right2);
7118 VectorNormalize (right2);
7120 vert[ 0] = org1[0] + width * right1[0];
7121 vert[ 1] = org1[1] + width * right1[1];
7122 vert[ 2] = org1[2] + width * right1[2];
7123 vert[ 3] = org1[0] - width * right1[0];
7124 vert[ 4] = org1[1] - width * right1[1];
7125 vert[ 5] = org1[2] - width * right1[2];
7126 vert[ 6] = org2[0] - width * right2[0];
7127 vert[ 7] = org2[1] - width * right2[1];
7128 vert[ 8] = org2[2] - width * right2[2];
7129 vert[ 9] = org2[0] + width * right2[0];
7130 vert[10] = org2[1] + width * right2[1];
7131 vert[11] = org2[2] + width * right2[2];
7134 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)
7136 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7137 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7138 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7139 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7140 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7141 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7142 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7143 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7144 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7145 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7146 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7147 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7150 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7155 VectorSet(v, x, y, z);
7156 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7157 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7159 if (i == mesh->numvertices)
7161 if (mesh->numvertices < mesh->maxvertices)
7163 VectorCopy(v, vertex3f);
7164 mesh->numvertices++;
7166 return mesh->numvertices;
7172 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7176 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7177 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7178 e = mesh->element3i + mesh->numtriangles * 3;
7179 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7181 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7182 if (mesh->numtriangles < mesh->maxtriangles)
7187 mesh->numtriangles++;
7189 element[1] = element[2];
7193 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7197 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7198 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7199 e = mesh->element3i + mesh->numtriangles * 3;
7200 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7202 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7203 if (mesh->numtriangles < mesh->maxtriangles)
7208 mesh->numtriangles++;
7210 element[1] = element[2];
7214 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7215 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7217 int planenum, planenum2;
7220 mplane_t *plane, *plane2;
7222 double temppoints[2][256*3];
7223 // figure out how large a bounding box we need to properly compute this brush
7225 for (w = 0;w < numplanes;w++)
7226 maxdist = max(maxdist, fabs(planes[w].dist));
7227 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7228 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7229 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7233 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7234 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7236 if (planenum2 == planenum)
7238 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);
7241 if (tempnumpoints < 3)
7243 // generate elements forming a triangle fan for this polygon
7244 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7248 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)
7250 texturelayer_t *layer;
7251 layer = t->currentlayers + t->currentnumlayers++;
7253 layer->depthmask = depthmask;
7254 layer->blendfunc1 = blendfunc1;
7255 layer->blendfunc2 = blendfunc2;
7256 layer->texture = texture;
7257 layer->texmatrix = *matrix;
7258 layer->color[0] = r;
7259 layer->color[1] = g;
7260 layer->color[2] = b;
7261 layer->color[3] = a;
7264 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7266 if(parms[0] == 0 && parms[1] == 0)
7268 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7269 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7274 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7277 index = parms[2] + r_refdef.scene.time * parms[3];
7278 index -= floor(index);
7279 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7282 case Q3WAVEFUNC_NONE:
7283 case Q3WAVEFUNC_NOISE:
7284 case Q3WAVEFUNC_COUNT:
7287 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7288 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7289 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7290 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7291 case Q3WAVEFUNC_TRIANGLE:
7293 f = index - floor(index);
7304 f = parms[0] + parms[1] * f;
7305 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7306 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7310 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7315 matrix4x4_t matrix, temp;
7316 switch(tcmod->tcmod)
7320 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7321 matrix = r_waterscrollmatrix;
7323 matrix = identitymatrix;
7325 case Q3TCMOD_ENTITYTRANSLATE:
7326 // this is used in Q3 to allow the gamecode to control texcoord
7327 // scrolling on the entity, which is not supported in darkplaces yet.
7328 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7330 case Q3TCMOD_ROTATE:
7331 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7332 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7333 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7336 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7338 case Q3TCMOD_SCROLL:
7339 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7341 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7342 w = (int) tcmod->parms[0];
7343 h = (int) tcmod->parms[1];
7344 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7346 idx = (int) floor(f * w * h);
7347 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7349 case Q3TCMOD_STRETCH:
7350 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7351 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7353 case Q3TCMOD_TRANSFORM:
7354 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7355 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7356 VectorSet(tcmat + 6, 0 , 0 , 1);
7357 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7358 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7360 case Q3TCMOD_TURBULENT:
7361 // this is handled in the RSurf_PrepareVertices function
7362 matrix = identitymatrix;
7366 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7369 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7371 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7372 char name[MAX_QPATH];
7373 skinframe_t *skinframe;
7374 unsigned char pixels[296*194];
7375 strlcpy(cache->name, skinname, sizeof(cache->name));
7376 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7377 if (developer_loading.integer)
7378 Con_Printf("loading %s\n", name);
7379 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7380 if (!skinframe || !skinframe->base)
7383 fs_offset_t filesize;
7385 f = FS_LoadFile(name, tempmempool, true, &filesize);
7388 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7389 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7393 cache->skinframe = skinframe;
7396 texture_t *R_GetCurrentTexture(texture_t *t)
7399 const entity_render_t *ent = rsurface.entity;
7400 dp_model_t *model = ent->model;
7401 q3shaderinfo_layer_tcmod_t *tcmod;
7403 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7404 return t->currentframe;
7405 t->update_lastrenderframe = r_textureframe;
7406 t->update_lastrenderentity = (void *)ent;
7408 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7409 t->camera_entity = ent->entitynumber;
7411 t->camera_entity = 0;
7413 // switch to an alternate material if this is a q1bsp animated material
7415 texture_t *texture = t;
7416 int s = rsurface.ent_skinnum;
7417 if ((unsigned int)s >= (unsigned int)model->numskins)
7419 if (model->skinscenes)
7421 if (model->skinscenes[s].framecount > 1)
7422 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7424 s = model->skinscenes[s].firstframe;
7427 t = t + s * model->num_surfaces;
7430 // use an alternate animation if the entity's frame is not 0,
7431 // and only if the texture has an alternate animation
7432 if (rsurface.ent_alttextures && t->anim_total[1])
7433 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7435 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7437 texture->currentframe = t;
7440 // update currentskinframe to be a qw skin or animation frame
7441 if (rsurface.ent_qwskin >= 0)
7443 i = rsurface.ent_qwskin;
7444 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7446 r_qwskincache_size = cl.maxclients;
7448 Mem_Free(r_qwskincache);
7449 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7451 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7452 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7453 t->currentskinframe = r_qwskincache[i].skinframe;
7454 if (t->currentskinframe == NULL)
7455 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7457 else if (t->numskinframes >= 2)
7458 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7459 if (t->backgroundnumskinframes >= 2)
7460 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7462 t->currentmaterialflags = t->basematerialflags;
7463 t->currentalpha = rsurface.colormod[3];
7464 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7465 t->currentalpha *= r_wateralpha.value;
7466 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7467 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7468 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7469 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7470 if (!(rsurface.ent_flags & RENDER_LIGHT))
7471 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7472 else if (FAKELIGHT_ENABLED)
7474 // no modellight if using fakelight for the map
7476 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7478 // pick a model lighting mode
7479 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7480 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7482 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7484 if (rsurface.ent_flags & RENDER_ADDITIVE)
7485 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7486 else if (t->currentalpha < 1)
7487 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7488 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7489 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7490 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7491 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7492 if (t->backgroundnumskinframes)
7493 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7494 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7496 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7497 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7500 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7501 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7502 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7504 // there is no tcmod
7505 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7507 t->currenttexmatrix = r_waterscrollmatrix;
7508 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7510 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7512 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7513 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7516 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7517 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7518 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7519 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7521 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7522 if (t->currentskinframe->qpixels)
7523 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7524 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7525 if (!t->basetexture)
7526 t->basetexture = r_texture_notexture;
7527 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7528 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7529 t->nmaptexture = t->currentskinframe->nmap;
7530 if (!t->nmaptexture)
7531 t->nmaptexture = r_texture_blanknormalmap;
7532 t->glosstexture = r_texture_black;
7533 t->glowtexture = t->currentskinframe->glow;
7534 t->fogtexture = t->currentskinframe->fog;
7535 t->reflectmasktexture = t->currentskinframe->reflect;
7536 if (t->backgroundnumskinframes)
7538 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7539 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7540 t->backgroundglosstexture = r_texture_black;
7541 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7542 if (!t->backgroundnmaptexture)
7543 t->backgroundnmaptexture = r_texture_blanknormalmap;
7547 t->backgroundbasetexture = r_texture_white;
7548 t->backgroundnmaptexture = r_texture_blanknormalmap;
7549 t->backgroundglosstexture = r_texture_black;
7550 t->backgroundglowtexture = NULL;
7552 t->specularpower = r_shadow_glossexponent.value;
7553 // TODO: store reference values for these in the texture?
7554 t->specularscale = 0;
7555 if (r_shadow_gloss.integer > 0)
7557 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7559 if (r_shadow_glossintensity.value > 0)
7561 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7562 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7563 t->specularscale = r_shadow_glossintensity.value;
7566 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7568 t->glosstexture = r_texture_white;
7569 t->backgroundglosstexture = r_texture_white;
7570 t->specularscale = r_shadow_gloss2intensity.value;
7571 t->specularpower = r_shadow_gloss2exponent.value;
7574 t->specularscale *= t->specularscalemod;
7575 t->specularpower *= t->specularpowermod;
7577 // lightmaps mode looks bad with dlights using actual texturing, so turn
7578 // off the colormap and glossmap, but leave the normalmap on as it still
7579 // accurately represents the shading involved
7580 if (gl_lightmaps.integer)
7582 t->basetexture = r_texture_grey128;
7583 t->pantstexture = r_texture_black;
7584 t->shirttexture = r_texture_black;
7585 t->nmaptexture = r_texture_blanknormalmap;
7586 t->glosstexture = r_texture_black;
7587 t->glowtexture = NULL;
7588 t->fogtexture = NULL;
7589 t->reflectmasktexture = NULL;
7590 t->backgroundbasetexture = NULL;
7591 t->backgroundnmaptexture = r_texture_blanknormalmap;
7592 t->backgroundglosstexture = r_texture_black;
7593 t->backgroundglowtexture = NULL;
7594 t->specularscale = 0;
7595 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7598 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7599 VectorClear(t->dlightcolor);
7600 t->currentnumlayers = 0;
7601 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7603 int blendfunc1, blendfunc2;
7605 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7607 blendfunc1 = GL_SRC_ALPHA;
7608 blendfunc2 = GL_ONE;
7610 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7612 blendfunc1 = GL_SRC_ALPHA;
7613 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7615 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7617 blendfunc1 = t->customblendfunc[0];
7618 blendfunc2 = t->customblendfunc[1];
7622 blendfunc1 = GL_ONE;
7623 blendfunc2 = GL_ZERO;
7625 // don't colormod evilblend textures
7626 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
7627 VectorSet(t->lightmapcolor, 1, 1, 1);
7628 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7629 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7631 // fullbright is not affected by r_refdef.lightmapintensity
7632 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]);
7633 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7634 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]);
7635 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7636 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]);
7640 vec3_t ambientcolor;
7642 // set the color tint used for lights affecting this surface
7643 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7645 // q3bsp has no lightmap updates, so the lightstylevalue that
7646 // would normally be baked into the lightmap must be
7647 // applied to the color
7648 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7649 if (model->type == mod_brushq3)
7650 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7651 colorscale *= r_refdef.lightmapintensity;
7652 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7653 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7654 // basic lit geometry
7655 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]);
7656 // add pants/shirt if needed
7657 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7658 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]);
7659 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7660 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]);
7661 // now add ambient passes if needed
7662 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7664 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]);
7665 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7666 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]);
7667 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7668 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]);
7671 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7672 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]);
7673 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7675 // if this is opaque use alpha blend which will darken the earlier
7678 // if this is an alpha blended material, all the earlier passes
7679 // were darkened by fog already, so we only need to add the fog
7680 // color ontop through the fog mask texture
7682 // if this is an additive blended material, all the earlier passes
7683 // were darkened by fog already, and we should not add fog color
7684 // (because the background was not darkened, there is no fog color
7685 // that was lost behind it).
7686 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]);
7690 return t->currentframe;
7693 rsurfacestate_t rsurface;
7695 void RSurf_ActiveWorldEntity(void)
7697 dp_model_t *model = r_refdef.scene.worldmodel;
7698 //if (rsurface.entity == r_refdef.scene.worldentity)
7700 rsurface.entity = r_refdef.scene.worldentity;
7701 rsurface.skeleton = NULL;
7702 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7703 rsurface.ent_skinnum = 0;
7704 rsurface.ent_qwskin = -1;
7705 rsurface.ent_shadertime = 0;
7706 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7707 rsurface.matrix = identitymatrix;
7708 rsurface.inversematrix = identitymatrix;
7709 rsurface.matrixscale = 1;
7710 rsurface.inversematrixscale = 1;
7711 R_EntityMatrix(&identitymatrix);
7712 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7713 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7714 rsurface.fograngerecip = r_refdef.fograngerecip;
7715 rsurface.fogheightfade = r_refdef.fogheightfade;
7716 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7717 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7718 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7719 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7720 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7721 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7722 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7723 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7724 rsurface.colormod[3] = 1;
7725 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);
7726 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7727 rsurface.frameblend[0].lerp = 1;
7728 rsurface.ent_alttextures = false;
7729 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7730 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7731 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7732 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7733 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7734 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7735 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7736 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7737 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7738 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7739 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7740 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7741 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7742 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7743 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7744 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7745 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7746 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7747 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7748 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7749 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7750 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7751 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7752 rsurface.modelelement3i = model->surfmesh.data_element3i;
7753 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7754 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7755 rsurface.modelelement3s = model->surfmesh.data_element3s;
7756 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7757 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7758 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7759 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7760 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7761 rsurface.modelsurfaces = model->data_surfaces;
7762 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7763 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7764 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7765 rsurface.modelgeneratedvertex = false;
7766 rsurface.batchgeneratedvertex = false;
7767 rsurface.batchfirstvertex = 0;
7768 rsurface.batchnumvertices = 0;
7769 rsurface.batchfirsttriangle = 0;
7770 rsurface.batchnumtriangles = 0;
7771 rsurface.batchvertex3f = NULL;
7772 rsurface.batchvertex3f_vertexbuffer = NULL;
7773 rsurface.batchvertex3f_bufferoffset = 0;
7774 rsurface.batchsvector3f = NULL;
7775 rsurface.batchsvector3f_vertexbuffer = NULL;
7776 rsurface.batchsvector3f_bufferoffset = 0;
7777 rsurface.batchtvector3f = NULL;
7778 rsurface.batchtvector3f_vertexbuffer = NULL;
7779 rsurface.batchtvector3f_bufferoffset = 0;
7780 rsurface.batchnormal3f = NULL;
7781 rsurface.batchnormal3f_vertexbuffer = NULL;
7782 rsurface.batchnormal3f_bufferoffset = 0;
7783 rsurface.batchlightmapcolor4f = NULL;
7784 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7785 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7786 rsurface.batchtexcoordtexture2f = NULL;
7787 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7788 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7789 rsurface.batchtexcoordlightmap2f = NULL;
7790 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7791 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7792 rsurface.batchvertexmesh = NULL;
7793 rsurface.batchvertexmeshbuffer = NULL;
7794 rsurface.batchvertex3fbuffer = NULL;
7795 rsurface.batchelement3i = NULL;
7796 rsurface.batchelement3i_indexbuffer = NULL;
7797 rsurface.batchelement3i_bufferoffset = 0;
7798 rsurface.batchelement3s = NULL;
7799 rsurface.batchelement3s_indexbuffer = NULL;
7800 rsurface.batchelement3s_bufferoffset = 0;
7801 rsurface.passcolor4f = NULL;
7802 rsurface.passcolor4f_vertexbuffer = NULL;
7803 rsurface.passcolor4f_bufferoffset = 0;
7806 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7808 dp_model_t *model = ent->model;
7809 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7811 rsurface.entity = (entity_render_t *)ent;
7812 rsurface.skeleton = ent->skeleton;
7813 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7814 rsurface.ent_skinnum = ent->skinnum;
7815 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;
7816 rsurface.ent_shadertime = ent->shadertime;
7817 rsurface.ent_flags = ent->flags;
7818 rsurface.matrix = ent->matrix;
7819 rsurface.inversematrix = ent->inversematrix;
7820 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7821 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7822 R_EntityMatrix(&rsurface.matrix);
7823 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7824 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7825 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7826 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7827 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7828 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7829 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7830 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7831 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7832 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7833 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7834 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7835 rsurface.colormod[3] = ent->alpha;
7836 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7837 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7838 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7839 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7840 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7841 if (ent->model->brush.submodel && !prepass)
7843 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7844 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7846 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7848 if (ent->animcache_vertex3f)
7850 rsurface.modelvertex3f = ent->animcache_vertex3f;
7851 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7852 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7853 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7854 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7855 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7856 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7858 else if (wanttangents)
7860 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7861 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7862 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7863 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7864 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7865 rsurface.modelvertexmesh = NULL;
7866 rsurface.modelvertexmeshbuffer = NULL;
7867 rsurface.modelvertex3fbuffer = NULL;
7869 else if (wantnormals)
7871 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7872 rsurface.modelsvector3f = NULL;
7873 rsurface.modeltvector3f = NULL;
7874 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7875 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7876 rsurface.modelvertexmesh = NULL;
7877 rsurface.modelvertexmeshbuffer = NULL;
7878 rsurface.modelvertex3fbuffer = NULL;
7882 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7883 rsurface.modelsvector3f = NULL;
7884 rsurface.modeltvector3f = NULL;
7885 rsurface.modelnormal3f = NULL;
7886 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7887 rsurface.modelvertexmesh = NULL;
7888 rsurface.modelvertexmeshbuffer = NULL;
7889 rsurface.modelvertex3fbuffer = NULL;
7891 rsurface.modelvertex3f_vertexbuffer = 0;
7892 rsurface.modelvertex3f_bufferoffset = 0;
7893 rsurface.modelsvector3f_vertexbuffer = 0;
7894 rsurface.modelsvector3f_bufferoffset = 0;
7895 rsurface.modeltvector3f_vertexbuffer = 0;
7896 rsurface.modeltvector3f_bufferoffset = 0;
7897 rsurface.modelnormal3f_vertexbuffer = 0;
7898 rsurface.modelnormal3f_bufferoffset = 0;
7899 rsurface.modelgeneratedvertex = true;
7903 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7904 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7905 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7906 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7907 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7908 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7909 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7910 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7911 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7912 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7913 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7914 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7915 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7916 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7917 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7918 rsurface.modelgeneratedvertex = false;
7920 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7921 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7922 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7923 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7924 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7925 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7926 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7927 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7928 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7929 rsurface.modelelement3i = model->surfmesh.data_element3i;
7930 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7931 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7932 rsurface.modelelement3s = model->surfmesh.data_element3s;
7933 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7934 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7935 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7936 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7937 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7938 rsurface.modelsurfaces = model->data_surfaces;
7939 rsurface.batchgeneratedvertex = false;
7940 rsurface.batchfirstvertex = 0;
7941 rsurface.batchnumvertices = 0;
7942 rsurface.batchfirsttriangle = 0;
7943 rsurface.batchnumtriangles = 0;
7944 rsurface.batchvertex3f = NULL;
7945 rsurface.batchvertex3f_vertexbuffer = NULL;
7946 rsurface.batchvertex3f_bufferoffset = 0;
7947 rsurface.batchsvector3f = NULL;
7948 rsurface.batchsvector3f_vertexbuffer = NULL;
7949 rsurface.batchsvector3f_bufferoffset = 0;
7950 rsurface.batchtvector3f = NULL;
7951 rsurface.batchtvector3f_vertexbuffer = NULL;
7952 rsurface.batchtvector3f_bufferoffset = 0;
7953 rsurface.batchnormal3f = NULL;
7954 rsurface.batchnormal3f_vertexbuffer = NULL;
7955 rsurface.batchnormal3f_bufferoffset = 0;
7956 rsurface.batchlightmapcolor4f = NULL;
7957 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7958 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7959 rsurface.batchtexcoordtexture2f = NULL;
7960 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7961 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7962 rsurface.batchtexcoordlightmap2f = NULL;
7963 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7964 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7965 rsurface.batchvertexmesh = NULL;
7966 rsurface.batchvertexmeshbuffer = NULL;
7967 rsurface.batchvertex3fbuffer = NULL;
7968 rsurface.batchelement3i = NULL;
7969 rsurface.batchelement3i_indexbuffer = NULL;
7970 rsurface.batchelement3i_bufferoffset = 0;
7971 rsurface.batchelement3s = NULL;
7972 rsurface.batchelement3s_indexbuffer = NULL;
7973 rsurface.batchelement3s_bufferoffset = 0;
7974 rsurface.passcolor4f = NULL;
7975 rsurface.passcolor4f_vertexbuffer = NULL;
7976 rsurface.passcolor4f_bufferoffset = 0;
7979 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)
7981 rsurface.entity = r_refdef.scene.worldentity;
7982 rsurface.skeleton = NULL;
7983 rsurface.ent_skinnum = 0;
7984 rsurface.ent_qwskin = -1;
7985 rsurface.ent_shadertime = shadertime;
7986 rsurface.ent_flags = entflags;
7987 rsurface.modelnumvertices = numvertices;
7988 rsurface.modelnumtriangles = numtriangles;
7989 rsurface.matrix = *matrix;
7990 rsurface.inversematrix = *inversematrix;
7991 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7992 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7993 R_EntityMatrix(&rsurface.matrix);
7994 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7995 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7996 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7997 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7998 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7999 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8000 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8001 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8002 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8003 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8004 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8005 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8006 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);
8007 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8008 rsurface.frameblend[0].lerp = 1;
8009 rsurface.ent_alttextures = false;
8010 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8011 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8014 rsurface.modelvertex3f = (float *)vertex3f;
8015 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8016 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8017 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8019 else if (wantnormals)
8021 rsurface.modelvertex3f = (float *)vertex3f;
8022 rsurface.modelsvector3f = NULL;
8023 rsurface.modeltvector3f = NULL;
8024 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8028 rsurface.modelvertex3f = (float *)vertex3f;
8029 rsurface.modelsvector3f = NULL;
8030 rsurface.modeltvector3f = NULL;
8031 rsurface.modelnormal3f = NULL;
8033 rsurface.modelvertexmesh = NULL;
8034 rsurface.modelvertexmeshbuffer = NULL;
8035 rsurface.modelvertex3fbuffer = NULL;
8036 rsurface.modelvertex3f_vertexbuffer = 0;
8037 rsurface.modelvertex3f_bufferoffset = 0;
8038 rsurface.modelsvector3f_vertexbuffer = 0;
8039 rsurface.modelsvector3f_bufferoffset = 0;
8040 rsurface.modeltvector3f_vertexbuffer = 0;
8041 rsurface.modeltvector3f_bufferoffset = 0;
8042 rsurface.modelnormal3f_vertexbuffer = 0;
8043 rsurface.modelnormal3f_bufferoffset = 0;
8044 rsurface.modelgeneratedvertex = true;
8045 rsurface.modellightmapcolor4f = (float *)color4f;
8046 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8047 rsurface.modellightmapcolor4f_bufferoffset = 0;
8048 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8049 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8050 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8051 rsurface.modeltexcoordlightmap2f = NULL;
8052 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8053 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8054 rsurface.modelelement3i = (int *)element3i;
8055 rsurface.modelelement3i_indexbuffer = NULL;
8056 rsurface.modelelement3i_bufferoffset = 0;
8057 rsurface.modelelement3s = (unsigned short *)element3s;
8058 rsurface.modelelement3s_indexbuffer = NULL;
8059 rsurface.modelelement3s_bufferoffset = 0;
8060 rsurface.modellightmapoffsets = NULL;
8061 rsurface.modelsurfaces = NULL;
8062 rsurface.batchgeneratedvertex = false;
8063 rsurface.batchfirstvertex = 0;
8064 rsurface.batchnumvertices = 0;
8065 rsurface.batchfirsttriangle = 0;
8066 rsurface.batchnumtriangles = 0;
8067 rsurface.batchvertex3f = NULL;
8068 rsurface.batchvertex3f_vertexbuffer = NULL;
8069 rsurface.batchvertex3f_bufferoffset = 0;
8070 rsurface.batchsvector3f = NULL;
8071 rsurface.batchsvector3f_vertexbuffer = NULL;
8072 rsurface.batchsvector3f_bufferoffset = 0;
8073 rsurface.batchtvector3f = NULL;
8074 rsurface.batchtvector3f_vertexbuffer = NULL;
8075 rsurface.batchtvector3f_bufferoffset = 0;
8076 rsurface.batchnormal3f = NULL;
8077 rsurface.batchnormal3f_vertexbuffer = NULL;
8078 rsurface.batchnormal3f_bufferoffset = 0;
8079 rsurface.batchlightmapcolor4f = NULL;
8080 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8081 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8082 rsurface.batchtexcoordtexture2f = NULL;
8083 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8084 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8085 rsurface.batchtexcoordlightmap2f = NULL;
8086 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8087 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8088 rsurface.batchvertexmesh = NULL;
8089 rsurface.batchvertexmeshbuffer = NULL;
8090 rsurface.batchvertex3fbuffer = NULL;
8091 rsurface.batchelement3i = NULL;
8092 rsurface.batchelement3i_indexbuffer = NULL;
8093 rsurface.batchelement3i_bufferoffset = 0;
8094 rsurface.batchelement3s = NULL;
8095 rsurface.batchelement3s_indexbuffer = NULL;
8096 rsurface.batchelement3s_bufferoffset = 0;
8097 rsurface.passcolor4f = NULL;
8098 rsurface.passcolor4f_vertexbuffer = NULL;
8099 rsurface.passcolor4f_bufferoffset = 0;
8101 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8103 if ((wantnormals || wanttangents) && !normal3f)
8105 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8106 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8108 if (wanttangents && !svector3f)
8110 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8111 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8112 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8117 float RSurf_FogPoint(const float *v)
8119 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8120 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8121 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8122 float FogHeightFade = r_refdef.fogheightfade;
8124 unsigned int fogmasktableindex;
8125 if (r_refdef.fogplaneviewabove)
8126 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8128 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8129 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8130 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8133 float RSurf_FogVertex(const float *v)
8135 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8136 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8137 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8138 float FogHeightFade = rsurface.fogheightfade;
8140 unsigned int fogmasktableindex;
8141 if (r_refdef.fogplaneviewabove)
8142 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8144 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8145 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8146 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8149 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8152 for (i = 0;i < numelements;i++)
8153 outelement3i[i] = inelement3i[i] + adjust;
8156 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8157 extern cvar_t gl_vbo;
8158 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8166 int surfacefirsttriangle;
8167 int surfacenumtriangles;
8168 int surfacefirstvertex;
8169 int surfaceendvertex;
8170 int surfacenumvertices;
8171 int batchnumvertices;
8172 int batchnumtriangles;
8176 qboolean dynamicvertex;
8180 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8182 q3shaderinfo_deform_t *deform;
8183 const msurface_t *surface, *firstsurface;
8184 r_vertexmesh_t *vertexmesh;
8185 if (!texturenumsurfaces)
8187 // find vertex range of this surface batch
8189 firstsurface = texturesurfacelist[0];
8190 firsttriangle = firstsurface->num_firsttriangle;
8191 batchnumvertices = 0;
8192 batchnumtriangles = 0;
8193 firstvertex = endvertex = firstsurface->num_firstvertex;
8194 for (i = 0;i < texturenumsurfaces;i++)
8196 surface = texturesurfacelist[i];
8197 if (surface != firstsurface + i)
8199 surfacefirstvertex = surface->num_firstvertex;
8200 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8201 surfacenumvertices = surface->num_vertices;
8202 surfacenumtriangles = surface->num_triangles;
8203 if (firstvertex > surfacefirstvertex)
8204 firstvertex = surfacefirstvertex;
8205 if (endvertex < surfaceendvertex)
8206 endvertex = surfaceendvertex;
8207 batchnumvertices += surfacenumvertices;
8208 batchnumtriangles += surfacenumtriangles;
8211 // we now know the vertex range used, and if there are any gaps in it
8212 rsurface.batchfirstvertex = firstvertex;
8213 rsurface.batchnumvertices = endvertex - firstvertex;
8214 rsurface.batchfirsttriangle = firsttriangle;
8215 rsurface.batchnumtriangles = batchnumtriangles;
8217 // this variable holds flags for which properties have been updated that
8218 // may require regenerating vertexmesh array...
8221 // check if any dynamic vertex processing must occur
8222 dynamicvertex = false;
8224 // if there is a chance of animated vertex colors, it's a dynamic batch
8225 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8227 dynamicvertex = true;
8228 batchneed |= BATCHNEED_NOGAPS;
8229 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8232 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8234 switch (deform->deform)
8237 case Q3DEFORM_PROJECTIONSHADOW:
8238 case Q3DEFORM_TEXT0:
8239 case Q3DEFORM_TEXT1:
8240 case Q3DEFORM_TEXT2:
8241 case Q3DEFORM_TEXT3:
8242 case Q3DEFORM_TEXT4:
8243 case Q3DEFORM_TEXT5:
8244 case Q3DEFORM_TEXT6:
8245 case Q3DEFORM_TEXT7:
8248 case Q3DEFORM_AUTOSPRITE:
8249 dynamicvertex = true;
8250 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8251 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8253 case Q3DEFORM_AUTOSPRITE2:
8254 dynamicvertex = true;
8255 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8256 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8258 case Q3DEFORM_NORMAL:
8259 dynamicvertex = true;
8260 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8261 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8264 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8265 break; // if wavefunc is a nop, ignore this transform
8266 dynamicvertex = true;
8267 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8268 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8270 case Q3DEFORM_BULGE:
8271 dynamicvertex = true;
8272 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8273 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8276 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8277 break; // if wavefunc is a nop, ignore this transform
8278 dynamicvertex = true;
8279 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8280 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8284 switch(rsurface.texture->tcgen.tcgen)
8287 case Q3TCGEN_TEXTURE:
8289 case Q3TCGEN_LIGHTMAP:
8290 dynamicvertex = true;
8291 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8292 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8294 case Q3TCGEN_VECTOR:
8295 dynamicvertex = true;
8296 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8297 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8299 case Q3TCGEN_ENVIRONMENT:
8300 dynamicvertex = true;
8301 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8302 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8305 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8307 dynamicvertex = true;
8308 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8309 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8312 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8314 dynamicvertex = true;
8315 batchneed |= BATCHNEED_NOGAPS;
8316 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8319 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8321 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8322 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8323 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8324 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8325 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8326 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8327 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8330 // when the model data has no vertex buffer (dynamic mesh), we need to
8332 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8333 batchneed |= BATCHNEED_NOGAPS;
8335 // if needsupdate, we have to do a dynamic vertex batch for sure
8336 if (needsupdate & batchneed)
8337 dynamicvertex = true;
8339 // see if we need to build vertexmesh from arrays
8340 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8341 dynamicvertex = true;
8343 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8344 // also some drivers strongly dislike firstvertex
8345 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8346 dynamicvertex = true;
8348 rsurface.batchvertex3f = rsurface.modelvertex3f;
8349 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8350 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8351 rsurface.batchsvector3f = rsurface.modelsvector3f;
8352 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8353 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8354 rsurface.batchtvector3f = rsurface.modeltvector3f;
8355 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8356 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8357 rsurface.batchnormal3f = rsurface.modelnormal3f;
8358 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8359 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8360 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8361 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8362 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8363 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8364 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8365 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8366 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8367 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8368 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8369 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8370 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8371 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8372 rsurface.batchelement3i = rsurface.modelelement3i;
8373 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8374 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8375 rsurface.batchelement3s = rsurface.modelelement3s;
8376 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8377 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8379 // if any dynamic vertex processing has to occur in software, we copy the
8380 // entire surface list together before processing to rebase the vertices
8381 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8383 // if any gaps exist and we do not have a static vertex buffer, we have to
8384 // copy the surface list together to avoid wasting upload bandwidth on the
8385 // vertices in the gaps.
8387 // if gaps exist and we have a static vertex buffer, we still have to
8388 // combine the index buffer ranges into one dynamic index buffer.
8390 // in all cases we end up with data that can be drawn in one call.
8394 // static vertex data, just set pointers...
8395 rsurface.batchgeneratedvertex = false;
8396 // if there are gaps, we want to build a combined index buffer,
8397 // otherwise use the original static buffer with an appropriate offset
8400 // build a new triangle elements array for this batch
8401 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8402 rsurface.batchfirsttriangle = 0;
8404 for (i = 0;i < texturenumsurfaces;i++)
8406 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8407 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8408 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8409 numtriangles += surfacenumtriangles;
8411 rsurface.batchelement3i_indexbuffer = NULL;
8412 rsurface.batchelement3i_bufferoffset = 0;
8413 rsurface.batchelement3s = NULL;
8414 rsurface.batchelement3s_indexbuffer = NULL;
8415 rsurface.batchelement3s_bufferoffset = 0;
8416 if (endvertex <= 65536)
8418 // make a 16bit (unsigned short) index array if possible
8419 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8420 for (i = 0;i < numtriangles*3;i++)
8421 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8427 // something needs software processing, do it for real...
8428 // we only directly handle separate array data in this case and then
8429 // generate interleaved data if needed...
8430 rsurface.batchgeneratedvertex = true;
8432 // now copy the vertex data into a combined array and make an index array
8433 // (this is what Quake3 does all the time)
8434 //if (gaps || rsurface.batchfirstvertex)
8436 rsurface.batchvertex3fbuffer = NULL;
8437 rsurface.batchvertexmesh = NULL;
8438 rsurface.batchvertexmeshbuffer = NULL;
8439 rsurface.batchvertex3f = NULL;
8440 rsurface.batchvertex3f_vertexbuffer = NULL;
8441 rsurface.batchvertex3f_bufferoffset = 0;
8442 rsurface.batchsvector3f = NULL;
8443 rsurface.batchsvector3f_vertexbuffer = NULL;
8444 rsurface.batchsvector3f_bufferoffset = 0;
8445 rsurface.batchtvector3f = NULL;
8446 rsurface.batchtvector3f_vertexbuffer = NULL;
8447 rsurface.batchtvector3f_bufferoffset = 0;
8448 rsurface.batchnormal3f = NULL;
8449 rsurface.batchnormal3f_vertexbuffer = NULL;
8450 rsurface.batchnormal3f_bufferoffset = 0;
8451 rsurface.batchlightmapcolor4f = NULL;
8452 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8453 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8454 rsurface.batchtexcoordtexture2f = NULL;
8455 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8456 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8457 rsurface.batchtexcoordlightmap2f = NULL;
8458 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8459 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8460 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8461 rsurface.batchelement3i_indexbuffer = NULL;
8462 rsurface.batchelement3i_bufferoffset = 0;
8463 rsurface.batchelement3s = NULL;
8464 rsurface.batchelement3s_indexbuffer = NULL;
8465 rsurface.batchelement3s_bufferoffset = 0;
8466 // we'll only be setting up certain arrays as needed
8467 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8468 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8469 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8470 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8471 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8472 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8473 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8475 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8476 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8478 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8479 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8480 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8481 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8482 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8483 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8486 for (i = 0;i < texturenumsurfaces;i++)
8488 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8489 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8490 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8491 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8492 // copy only the data requested
8493 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8494 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8495 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8497 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8498 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8499 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8500 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8501 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8503 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8504 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8506 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8507 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8508 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8509 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8510 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8511 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8513 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8514 numvertices += surfacenumvertices;
8515 numtriangles += surfacenumtriangles;
8518 // generate a 16bit index array as well if possible
8519 // (in general, dynamic batches fit)
8520 if (numvertices <= 65536)
8522 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8523 for (i = 0;i < numtriangles*3;i++)
8524 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8527 // since we've copied everything, the batch now starts at 0
8528 rsurface.batchfirstvertex = 0;
8529 rsurface.batchnumvertices = batchnumvertices;
8530 rsurface.batchfirsttriangle = 0;
8531 rsurface.batchnumtriangles = batchnumtriangles;
8534 // q1bsp surfaces rendered in vertex color mode have to have colors
8535 // calculated based on lightstyles
8536 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8538 // generate color arrays for the surfaces in this list
8543 const unsigned char *lm;
8544 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8545 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8546 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8548 for (i = 0;i < texturenumsurfaces;i++)
8550 surface = texturesurfacelist[i];
8551 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8552 surfacenumvertices = surface->num_vertices;
8553 if (surface->lightmapinfo->samples)
8555 for (j = 0;j < surfacenumvertices;j++)
8557 lm = surface->lightmapinfo->samples + offsets[j];
8558 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8559 VectorScale(lm, scale, c);
8560 if (surface->lightmapinfo->styles[1] != 255)
8562 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8564 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8565 VectorMA(c, scale, lm, c);
8566 if (surface->lightmapinfo->styles[2] != 255)
8569 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8570 VectorMA(c, scale, lm, c);
8571 if (surface->lightmapinfo->styles[3] != 255)
8574 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8575 VectorMA(c, scale, lm, c);
8582 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);
8588 for (j = 0;j < surfacenumvertices;j++)
8590 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8597 // if vertices are deformed (sprite flares and things in maps, possibly
8598 // water waves, bulges and other deformations), modify the copied vertices
8600 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8602 switch (deform->deform)
8605 case Q3DEFORM_PROJECTIONSHADOW:
8606 case Q3DEFORM_TEXT0:
8607 case Q3DEFORM_TEXT1:
8608 case Q3DEFORM_TEXT2:
8609 case Q3DEFORM_TEXT3:
8610 case Q3DEFORM_TEXT4:
8611 case Q3DEFORM_TEXT5:
8612 case Q3DEFORM_TEXT6:
8613 case Q3DEFORM_TEXT7:
8616 case Q3DEFORM_AUTOSPRITE:
8617 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8618 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8619 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8620 VectorNormalize(newforward);
8621 VectorNormalize(newright);
8622 VectorNormalize(newup);
8623 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8624 // rsurface.batchvertex3f_vertexbuffer = NULL;
8625 // rsurface.batchvertex3f_bufferoffset = 0;
8626 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8627 // rsurface.batchsvector3f_vertexbuffer = NULL;
8628 // rsurface.batchsvector3f_bufferoffset = 0;
8629 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8630 // rsurface.batchtvector3f_vertexbuffer = NULL;
8631 // rsurface.batchtvector3f_bufferoffset = 0;
8632 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8633 // rsurface.batchnormal3f_vertexbuffer = NULL;
8634 // rsurface.batchnormal3f_bufferoffset = 0;
8635 // a single autosprite surface can contain multiple sprites...
8636 for (j = 0;j < batchnumvertices - 3;j += 4)
8638 VectorClear(center);
8639 for (i = 0;i < 4;i++)
8640 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8641 VectorScale(center, 0.25f, center);
8642 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8643 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8644 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8645 for (i = 0;i < 4;i++)
8647 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8648 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8651 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8652 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8653 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);
8655 case Q3DEFORM_AUTOSPRITE2:
8656 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8657 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8658 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8659 VectorNormalize(newforward);
8660 VectorNormalize(newright);
8661 VectorNormalize(newup);
8662 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8663 // rsurface.batchvertex3f_vertexbuffer = NULL;
8664 // rsurface.batchvertex3f_bufferoffset = 0;
8666 const float *v1, *v2;
8676 memset(shortest, 0, sizeof(shortest));
8677 // a single autosprite surface can contain multiple sprites...
8678 for (j = 0;j < batchnumvertices - 3;j += 4)
8680 VectorClear(center);
8681 for (i = 0;i < 4;i++)
8682 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8683 VectorScale(center, 0.25f, center);
8684 // find the two shortest edges, then use them to define the
8685 // axis vectors for rotating around the central axis
8686 for (i = 0;i < 6;i++)
8688 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8689 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8690 l = VectorDistance2(v1, v2);
8691 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8693 l += (1.0f / 1024.0f);
8694 if (shortest[0].length2 > l || i == 0)
8696 shortest[1] = shortest[0];
8697 shortest[0].length2 = l;
8698 shortest[0].v1 = v1;
8699 shortest[0].v2 = v2;
8701 else if (shortest[1].length2 > l || i == 1)
8703 shortest[1].length2 = l;
8704 shortest[1].v1 = v1;
8705 shortest[1].v2 = v2;
8708 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8709 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8710 // this calculates the right vector from the shortest edge
8711 // and the up vector from the edge midpoints
8712 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8713 VectorNormalize(right);
8714 VectorSubtract(end, start, up);
8715 VectorNormalize(up);
8716 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8717 VectorSubtract(rsurface.localvieworigin, center, forward);
8718 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8719 VectorNegate(forward, forward);
8720 VectorReflect(forward, 0, up, forward);
8721 VectorNormalize(forward);
8722 CrossProduct(up, forward, newright);
8723 VectorNormalize(newright);
8724 // rotate the quad around the up axis vector, this is made
8725 // especially easy by the fact we know the quad is flat,
8726 // so we only have to subtract the center position and
8727 // measure distance along the right vector, and then
8728 // multiply that by the newright vector and add back the
8730 // we also need to subtract the old position to undo the
8731 // displacement from the center, which we do with a
8732 // DotProduct, the subtraction/addition of center is also
8733 // optimized into DotProducts here
8734 l = DotProduct(right, center);
8735 for (i = 0;i < 4;i++)
8737 v1 = rsurface.batchvertex3f + 3*(j+i);
8738 f = DotProduct(right, v1) - l;
8739 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8743 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8745 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8746 // rsurface.batchnormal3f_vertexbuffer = NULL;
8747 // rsurface.batchnormal3f_bufferoffset = 0;
8748 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8750 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8752 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8753 // rsurface.batchsvector3f_vertexbuffer = NULL;
8754 // rsurface.batchsvector3f_bufferoffset = 0;
8755 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8756 // rsurface.batchtvector3f_vertexbuffer = NULL;
8757 // rsurface.batchtvector3f_bufferoffset = 0;
8758 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);
8761 case Q3DEFORM_NORMAL:
8762 // deform the normals to make reflections wavey
8763 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8764 rsurface.batchnormal3f_vertexbuffer = NULL;
8765 rsurface.batchnormal3f_bufferoffset = 0;
8766 for (j = 0;j < batchnumvertices;j++)
8769 float *normal = rsurface.batchnormal3f + 3*j;
8770 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8771 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8772 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]);
8773 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]);
8774 VectorNormalize(normal);
8776 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8778 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8779 // rsurface.batchsvector3f_vertexbuffer = NULL;
8780 // rsurface.batchsvector3f_bufferoffset = 0;
8781 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8782 // rsurface.batchtvector3f_vertexbuffer = NULL;
8783 // rsurface.batchtvector3f_bufferoffset = 0;
8784 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);
8788 // deform vertex array to make wavey water and flags and such
8789 waveparms[0] = deform->waveparms[0];
8790 waveparms[1] = deform->waveparms[1];
8791 waveparms[2] = deform->waveparms[2];
8792 waveparms[3] = deform->waveparms[3];
8793 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8794 break; // if wavefunc is a nop, don't make a dynamic vertex array
8795 // this is how a divisor of vertex influence on deformation
8796 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8797 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8798 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8799 // rsurface.batchvertex3f_vertexbuffer = NULL;
8800 // rsurface.batchvertex3f_bufferoffset = 0;
8801 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8802 // rsurface.batchnormal3f_vertexbuffer = NULL;
8803 // rsurface.batchnormal3f_bufferoffset = 0;
8804 for (j = 0;j < batchnumvertices;j++)
8806 // if the wavefunc depends on time, evaluate it per-vertex
8809 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8810 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8812 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8814 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8815 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8816 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8818 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8819 // rsurface.batchsvector3f_vertexbuffer = NULL;
8820 // rsurface.batchsvector3f_bufferoffset = 0;
8821 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8822 // rsurface.batchtvector3f_vertexbuffer = NULL;
8823 // rsurface.batchtvector3f_bufferoffset = 0;
8824 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);
8827 case Q3DEFORM_BULGE:
8828 // deform vertex array to make the surface have moving bulges
8829 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8830 // rsurface.batchvertex3f_vertexbuffer = NULL;
8831 // rsurface.batchvertex3f_bufferoffset = 0;
8832 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8833 // rsurface.batchnormal3f_vertexbuffer = NULL;
8834 // rsurface.batchnormal3f_bufferoffset = 0;
8835 for (j = 0;j < batchnumvertices;j++)
8837 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8838 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8840 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8841 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8842 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8844 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8845 // rsurface.batchsvector3f_vertexbuffer = NULL;
8846 // rsurface.batchsvector3f_bufferoffset = 0;
8847 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8848 // rsurface.batchtvector3f_vertexbuffer = NULL;
8849 // rsurface.batchtvector3f_bufferoffset = 0;
8850 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);
8854 // deform vertex array
8855 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8856 break; // if wavefunc is a nop, don't make a dynamic vertex array
8857 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8858 VectorScale(deform->parms, scale, waveparms);
8859 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8860 // rsurface.batchvertex3f_vertexbuffer = NULL;
8861 // rsurface.batchvertex3f_bufferoffset = 0;
8862 for (j = 0;j < batchnumvertices;j++)
8863 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8868 // generate texcoords based on the chosen texcoord source
8869 switch(rsurface.texture->tcgen.tcgen)
8872 case Q3TCGEN_TEXTURE:
8874 case Q3TCGEN_LIGHTMAP:
8875 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8876 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8877 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8878 if (rsurface.batchtexcoordlightmap2f)
8879 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8881 case Q3TCGEN_VECTOR:
8882 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8883 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8884 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8885 for (j = 0;j < batchnumvertices;j++)
8887 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8888 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8891 case Q3TCGEN_ENVIRONMENT:
8892 // make environment reflections using a spheremap
8893 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8894 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8895 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8896 for (j = 0;j < batchnumvertices;j++)
8898 // identical to Q3A's method, but executed in worldspace so
8899 // carried models can be shiny too
8901 float viewer[3], d, reflected[3], worldreflected[3];
8903 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8904 // VectorNormalize(viewer);
8906 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8908 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8909 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8910 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8911 // note: this is proportinal to viewer, so we can normalize later
8913 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8914 VectorNormalize(worldreflected);
8916 // note: this sphere map only uses world x and z!
8917 // so positive and negative y will LOOK THE SAME.
8918 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8919 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8923 // the only tcmod that needs software vertex processing is turbulent, so
8924 // check for it here and apply the changes if needed
8925 // and we only support that as the first one
8926 // (handling a mixture of turbulent and other tcmods would be problematic
8927 // without punting it entirely to a software path)
8928 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8930 amplitude = rsurface.texture->tcmods[0].parms[1];
8931 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8932 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8933 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8934 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8935 for (j = 0;j < batchnumvertices;j++)
8937 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);
8938 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8942 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8944 // convert the modified arrays to vertex structs
8945 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8946 // rsurface.batchvertexmeshbuffer = NULL;
8947 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8948 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8949 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8950 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8951 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8952 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
8953 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
8955 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8957 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
8958 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
8961 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
8962 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8963 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
8964 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
8965 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8966 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
8967 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
8968 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8969 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
8973 void RSurf_DrawBatch(void)
8975 // sometimes a zero triangle surface (usually a degenerate patch) makes it
8976 // through the pipeline, killing it earlier in the pipeline would have
8977 // per-surface overhead rather than per-batch overhead, so it's best to
8978 // reject it here, before it hits glDraw.
8979 if (rsurface.batchnumtriangles == 0)
8982 // batch debugging code
8983 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
8989 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
8990 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
8993 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
8995 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
8997 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
8998 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);
9005 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);
9008 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9010 // pick the closest matching water plane
9011 int planeindex, vertexindex, bestplaneindex = -1;
9015 r_waterstate_waterplane_t *p;
9016 qboolean prepared = false;
9018 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9020 if(p->camera_entity != rsurface.texture->camera_entity)
9025 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9027 if(rsurface.batchnumvertices == 0)
9030 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9032 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9033 d += fabs(PlaneDiff(vert, &p->plane));
9035 if (bestd > d || bestplaneindex < 0)
9038 bestplaneindex = planeindex;
9041 return bestplaneindex;
9042 // NOTE: this MAY return a totally unrelated water plane; we can ignore
9043 // this situation though, as it might be better to render single larger
9044 // batches with useless stuff (backface culled for example) than to
9045 // render multiple smaller batches
9048 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9051 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9052 rsurface.passcolor4f_vertexbuffer = 0;
9053 rsurface.passcolor4f_bufferoffset = 0;
9054 for (i = 0;i < rsurface.batchnumvertices;i++)
9055 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9058 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9065 if (rsurface.passcolor4f)
9067 // generate color arrays
9068 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9069 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9070 rsurface.passcolor4f_vertexbuffer = 0;
9071 rsurface.passcolor4f_bufferoffset = 0;
9072 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)
9074 f = RSurf_FogVertex(v);
9083 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9084 rsurface.passcolor4f_vertexbuffer = 0;
9085 rsurface.passcolor4f_bufferoffset = 0;
9086 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9088 f = RSurf_FogVertex(v);
9097 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9104 if (!rsurface.passcolor4f)
9106 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9107 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9108 rsurface.passcolor4f_vertexbuffer = 0;
9109 rsurface.passcolor4f_bufferoffset = 0;
9110 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)
9112 f = RSurf_FogVertex(v);
9113 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9114 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9115 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9120 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9125 if (!rsurface.passcolor4f)
9127 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9128 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9129 rsurface.passcolor4f_vertexbuffer = 0;
9130 rsurface.passcolor4f_bufferoffset = 0;
9131 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9140 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9145 if (!rsurface.passcolor4f)
9147 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9148 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9149 rsurface.passcolor4f_vertexbuffer = 0;
9150 rsurface.passcolor4f_bufferoffset = 0;
9151 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9153 c2[0] = c[0] + r_refdef.scene.ambient;
9154 c2[1] = c[1] + r_refdef.scene.ambient;
9155 c2[2] = c[2] + r_refdef.scene.ambient;
9160 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9163 rsurface.passcolor4f = NULL;
9164 rsurface.passcolor4f_vertexbuffer = 0;
9165 rsurface.passcolor4f_bufferoffset = 0;
9166 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9167 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9168 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9169 GL_Color(r, g, b, a);
9170 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9174 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9176 // TODO: optimize applyfog && applycolor case
9177 // just apply fog if necessary, and tint the fog color array if necessary
9178 rsurface.passcolor4f = NULL;
9179 rsurface.passcolor4f_vertexbuffer = 0;
9180 rsurface.passcolor4f_bufferoffset = 0;
9181 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9182 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9183 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9184 GL_Color(r, g, b, a);
9188 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9191 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9192 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9193 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9194 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9195 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9196 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9197 GL_Color(r, g, b, a);
9201 static void RSurf_DrawBatch_GL11_ClampColor(void)
9206 if (!rsurface.passcolor4f)
9208 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9210 c2[0] = bound(0.0f, c1[0], 1.0f);
9211 c2[1] = bound(0.0f, c1[1], 1.0f);
9212 c2[2] = bound(0.0f, c1[2], 1.0f);
9213 c2[3] = bound(0.0f, c1[3], 1.0f);
9217 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9227 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9228 rsurface.passcolor4f_vertexbuffer = 0;
9229 rsurface.passcolor4f_bufferoffset = 0;
9230 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)
9232 f = -DotProduct(r_refdef.view.forward, n);
9234 f = f * 0.85 + 0.15; // work around so stuff won't get black
9235 f *= r_refdef.lightmapintensity;
9236 Vector4Set(c, f, f, f, 1);
9240 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9242 RSurf_DrawBatch_GL11_ApplyFakeLight();
9243 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9244 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9245 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9246 GL_Color(r, g, b, a);
9250 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9258 vec3_t ambientcolor;
9259 vec3_t diffusecolor;
9263 VectorCopy(rsurface.modellight_lightdir, lightdir);
9264 f = 0.5f * r_refdef.lightmapintensity;
9265 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9266 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9267 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9268 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9269 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9270 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9272 if (VectorLength2(diffusecolor) > 0)
9274 // q3-style directional shading
9275 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9276 rsurface.passcolor4f_vertexbuffer = 0;
9277 rsurface.passcolor4f_bufferoffset = 0;
9278 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)
9280 if ((f = DotProduct(n, lightdir)) > 0)
9281 VectorMA(ambientcolor, f, diffusecolor, c);
9283 VectorCopy(ambientcolor, c);
9290 *applycolor = false;
9294 *r = ambientcolor[0];
9295 *g = ambientcolor[1];
9296 *b = ambientcolor[2];
9297 rsurface.passcolor4f = NULL;
9298 rsurface.passcolor4f_vertexbuffer = 0;
9299 rsurface.passcolor4f_bufferoffset = 0;
9303 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9305 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9306 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9307 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9308 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9309 GL_Color(r, g, b, a);
9313 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9319 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9321 f = 1 - RSurf_FogVertex(v);
9329 void RSurf_SetupDepthAndCulling(void)
9331 // submodels are biased to avoid z-fighting with world surfaces that they
9332 // may be exactly overlapping (avoids z-fighting artifacts on certain
9333 // doors and things in Quake maps)
9334 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9335 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9336 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9337 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9340 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9342 // transparent sky would be ridiculous
9343 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9345 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9346 skyrenderlater = true;
9347 RSurf_SetupDepthAndCulling();
9349 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9350 // skymasking on them, and Quake3 never did sky masking (unlike
9351 // software Quake and software Quake2), so disable the sky masking
9352 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9353 // and skymasking also looks very bad when noclipping outside the
9354 // level, so don't use it then either.
9355 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9357 R_Mesh_ResetTextureState();
9358 if (skyrendermasked)
9360 R_SetupShader_DepthOrShadow();
9361 // depth-only (masking)
9362 GL_ColorMask(0,0,0,0);
9363 // just to make sure that braindead drivers don't draw
9364 // anything despite that colormask...
9365 GL_BlendFunc(GL_ZERO, GL_ONE);
9366 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9367 if (rsurface.batchvertex3fbuffer)
9368 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9370 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9374 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9376 GL_BlendFunc(GL_ONE, GL_ZERO);
9377 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9378 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9379 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9382 if (skyrendermasked)
9383 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9385 R_Mesh_ResetTextureState();
9386 GL_Color(1, 1, 1, 1);
9389 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9390 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9391 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9393 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9397 // render screenspace normalmap to texture
9399 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9404 // bind lightmap texture
9406 // water/refraction/reflection/camera surfaces have to be handled specially
9407 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9409 int start, end, startplaneindex;
9410 for (start = 0;start < texturenumsurfaces;start = end)
9412 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9413 if(startplaneindex < 0)
9415 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9416 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9420 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9422 // now that we have a batch using the same planeindex, render it
9423 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9425 // render water or distortion background
9427 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));
9429 // blend surface on top
9430 GL_DepthMask(false);
9431 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9434 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9436 // render surface with reflection texture as input
9437 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9438 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));
9445 // render surface batch normally
9446 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9447 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9451 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9453 // OpenGL 1.3 path - anything not completely ancient
9454 qboolean applycolor;
9457 const texturelayer_t *layer;
9458 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9459 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9461 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9464 int layertexrgbscale;
9465 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9467 if (layerindex == 0)
9471 GL_AlphaTest(false);
9472 GL_DepthFunc(GL_EQUAL);
9475 GL_DepthMask(layer->depthmask && writedepth);
9476 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9477 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9479 layertexrgbscale = 4;
9480 VectorScale(layer->color, 0.25f, layercolor);
9482 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9484 layertexrgbscale = 2;
9485 VectorScale(layer->color, 0.5f, layercolor);
9489 layertexrgbscale = 1;
9490 VectorScale(layer->color, 1.0f, layercolor);
9492 layercolor[3] = layer->color[3];
9493 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9494 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9495 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9496 switch (layer->type)
9498 case TEXTURELAYERTYPE_LITTEXTURE:
9499 // single-pass lightmapped texture with 2x rgbscale
9500 R_Mesh_TexBind(0, r_texture_white);
9501 R_Mesh_TexMatrix(0, NULL);
9502 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9503 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9504 R_Mesh_TexBind(1, layer->texture);
9505 R_Mesh_TexMatrix(1, &layer->texmatrix);
9506 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9507 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9508 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9509 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9510 else if (FAKELIGHT_ENABLED)
9511 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9512 else if (rsurface.uselightmaptexture)
9513 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9515 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9517 case TEXTURELAYERTYPE_TEXTURE:
9518 // singletexture unlit texture with transparency support
9519 R_Mesh_TexBind(0, layer->texture);
9520 R_Mesh_TexMatrix(0, &layer->texmatrix);
9521 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9522 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9523 R_Mesh_TexBind(1, 0);
9524 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9525 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9527 case TEXTURELAYERTYPE_FOG:
9528 // singletexture fogging
9531 R_Mesh_TexBind(0, layer->texture);
9532 R_Mesh_TexMatrix(0, &layer->texmatrix);
9533 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9534 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9538 R_Mesh_TexBind(0, 0);
9539 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9541 R_Mesh_TexBind(1, 0);
9542 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9543 // generate a color array for the fog pass
9544 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9545 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9549 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9552 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9554 GL_DepthFunc(GL_LEQUAL);
9555 GL_AlphaTest(false);
9559 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9561 // OpenGL 1.1 - crusty old voodoo path
9564 const texturelayer_t *layer;
9565 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);
9566 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9568 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9570 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9572 if (layerindex == 0)
9576 GL_AlphaTest(false);
9577 GL_DepthFunc(GL_EQUAL);
9580 GL_DepthMask(layer->depthmask && writedepth);
9581 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9582 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9583 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9584 switch (layer->type)
9586 case TEXTURELAYERTYPE_LITTEXTURE:
9587 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9589 // two-pass lit texture with 2x rgbscale
9590 // first the lightmap pass
9591 R_Mesh_TexBind(0, r_texture_white);
9592 R_Mesh_TexMatrix(0, NULL);
9593 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9594 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9595 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9596 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9597 else if (FAKELIGHT_ENABLED)
9598 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9599 else if (rsurface.uselightmaptexture)
9600 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9602 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9603 // then apply the texture to it
9604 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9605 R_Mesh_TexBind(0, layer->texture);
9606 R_Mesh_TexMatrix(0, &layer->texmatrix);
9607 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9608 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9609 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);
9613 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9614 R_Mesh_TexBind(0, layer->texture);
9615 R_Mesh_TexMatrix(0, &layer->texmatrix);
9616 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9617 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9618 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9619 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);
9621 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);
9624 case TEXTURELAYERTYPE_TEXTURE:
9625 // singletexture unlit texture with transparency support
9626 R_Mesh_TexBind(0, layer->texture);
9627 R_Mesh_TexMatrix(0, &layer->texmatrix);
9628 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9629 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9630 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);
9632 case TEXTURELAYERTYPE_FOG:
9633 // singletexture fogging
9636 R_Mesh_TexBind(0, layer->texture);
9637 R_Mesh_TexMatrix(0, &layer->texmatrix);
9638 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9639 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9643 R_Mesh_TexBind(0, 0);
9644 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9646 // generate a color array for the fog pass
9647 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9648 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9652 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9655 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9657 GL_DepthFunc(GL_LEQUAL);
9658 GL_AlphaTest(false);
9662 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9666 r_vertexgeneric_t *batchvertex;
9669 // R_Mesh_ResetTextureState();
9670 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9672 if(rsurface.texture && rsurface.texture->currentskinframe)
9674 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9675 c[3] *= rsurface.texture->currentalpha;
9685 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9687 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9688 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9689 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9692 // brighten it up (as texture value 127 means "unlit")
9693 c[0] *= 2 * r_refdef.view.colorscale;
9694 c[1] *= 2 * r_refdef.view.colorscale;
9695 c[2] *= 2 * r_refdef.view.colorscale;
9697 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9698 c[3] *= r_wateralpha.value;
9700 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9702 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9703 GL_DepthMask(false);
9705 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9707 GL_BlendFunc(GL_ONE, GL_ONE);
9708 GL_DepthMask(false);
9710 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9712 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9713 GL_DepthMask(false);
9715 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9717 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9718 GL_DepthMask(false);
9722 GL_BlendFunc(GL_ONE, GL_ZERO);
9723 GL_DepthMask(writedepth);
9726 if (r_showsurfaces.integer == 3)
9728 rsurface.passcolor4f = NULL;
9730 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9732 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9734 rsurface.passcolor4f = NULL;
9735 rsurface.passcolor4f_vertexbuffer = 0;
9736 rsurface.passcolor4f_bufferoffset = 0;
9738 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9740 qboolean applycolor = true;
9743 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9745 r_refdef.lightmapintensity = 1;
9746 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9747 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9749 else if (FAKELIGHT_ENABLED)
9751 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9753 r_refdef.lightmapintensity = r_fakelight_intensity.value;
9754 RSurf_DrawBatch_GL11_ApplyFakeLight();
9755 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9759 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9761 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9762 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9763 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9766 if(!rsurface.passcolor4f)
9767 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9769 RSurf_DrawBatch_GL11_ApplyAmbient();
9770 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9771 if(r_refdef.fogenabled)
9772 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9773 RSurf_DrawBatch_GL11_ClampColor();
9775 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9776 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9779 else if (!r_refdef.view.showdebug)
9781 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9782 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9783 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9785 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9786 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9788 R_Mesh_PrepareVertices_Generic_Unlock();
9791 else if (r_showsurfaces.integer == 4)
9793 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9794 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9795 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9797 unsigned char c = (vi << 3) * (1.0f / 256.0f);
9798 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9799 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9801 R_Mesh_PrepareVertices_Generic_Unlock();
9804 else if (r_showsurfaces.integer == 2)
9807 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9808 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9809 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9811 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9812 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9813 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9814 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9815 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9816 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9817 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9819 R_Mesh_PrepareVertices_Generic_Unlock();
9820 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9824 int texturesurfaceindex;
9826 const msurface_t *surface;
9827 float surfacecolor4f[4];
9828 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9829 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9831 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9833 surface = texturesurfacelist[texturesurfaceindex];
9834 k = (int)(((size_t)surface) / sizeof(msurface_t));
9835 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9836 for (j = 0;j < surface->num_vertices;j++)
9838 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9839 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9843 R_Mesh_PrepareVertices_Generic_Unlock();
9848 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9851 RSurf_SetupDepthAndCulling();
9852 if (r_showsurfaces.integer)
9854 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9857 switch (vid.renderpath)
9859 case RENDERPATH_GL20:
9860 case RENDERPATH_D3D9:
9861 case RENDERPATH_D3D10:
9862 case RENDERPATH_D3D11:
9863 case RENDERPATH_SOFT:
9864 case RENDERPATH_GLES2:
9865 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9867 case RENDERPATH_GL13:
9868 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9870 case RENDERPATH_GL11:
9871 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9877 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9880 RSurf_SetupDepthAndCulling();
9881 if (r_showsurfaces.integer)
9883 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9886 switch (vid.renderpath)
9888 case RENDERPATH_GL20:
9889 case RENDERPATH_D3D9:
9890 case RENDERPATH_D3D10:
9891 case RENDERPATH_D3D11:
9892 case RENDERPATH_SOFT:
9893 case RENDERPATH_GLES2:
9894 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9896 case RENDERPATH_GL13:
9897 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9899 case RENDERPATH_GL11:
9900 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9906 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9909 int texturenumsurfaces, endsurface;
9911 const msurface_t *surface;
9912 #define MAXBATCH_TRANSPARENTSURFACES 256
9913 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9915 // if the model is static it doesn't matter what value we give for
9916 // wantnormals and wanttangents, so this logic uses only rules applicable
9917 // to a model, knowing that they are meaningless otherwise
9918 if (ent == r_refdef.scene.worldentity)
9919 RSurf_ActiveWorldEntity();
9920 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9921 RSurf_ActiveModelEntity(ent, false, false, false);
9924 switch (vid.renderpath)
9926 case RENDERPATH_GL20:
9927 case RENDERPATH_D3D9:
9928 case RENDERPATH_D3D10:
9929 case RENDERPATH_D3D11:
9930 case RENDERPATH_SOFT:
9931 case RENDERPATH_GLES2:
9932 RSurf_ActiveModelEntity(ent, true, true, false);
9934 case RENDERPATH_GL13:
9935 case RENDERPATH_GL11:
9936 RSurf_ActiveModelEntity(ent, true, false, false);
9941 if (r_transparentdepthmasking.integer)
9943 qboolean setup = false;
9944 for (i = 0;i < numsurfaces;i = j)
9947 surface = rsurface.modelsurfaces + surfacelist[i];
9948 texture = surface->texture;
9949 rsurface.texture = R_GetCurrentTexture(texture);
9950 rsurface.lightmaptexture = NULL;
9951 rsurface.deluxemaptexture = NULL;
9952 rsurface.uselightmaptexture = false;
9953 // scan ahead until we find a different texture
9954 endsurface = min(i + 1024, numsurfaces);
9955 texturenumsurfaces = 0;
9956 texturesurfacelist[texturenumsurfaces++] = surface;
9957 for (;j < endsurface;j++)
9959 surface = rsurface.modelsurfaces + surfacelist[j];
9960 if (texture != surface->texture)
9962 texturesurfacelist[texturenumsurfaces++] = surface;
9964 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9966 // render the range of surfaces as depth
9970 GL_ColorMask(0,0,0,0);
9973 GL_BlendFunc(GL_ONE, GL_ZERO);
9975 // R_Mesh_ResetTextureState();
9976 R_SetupShader_DepthOrShadow();
9978 RSurf_SetupDepthAndCulling();
9979 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9980 if (rsurface.batchvertex3fbuffer)
9981 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9983 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9987 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9990 for (i = 0;i < numsurfaces;i = j)
9993 surface = rsurface.modelsurfaces + surfacelist[i];
9994 texture = surface->texture;
9995 rsurface.texture = R_GetCurrentTexture(texture);
9996 // scan ahead until we find a different texture
9997 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
9998 texturenumsurfaces = 0;
9999 texturesurfacelist[texturenumsurfaces++] = surface;
10000 if(FAKELIGHT_ENABLED)
10002 rsurface.lightmaptexture = NULL;
10003 rsurface.deluxemaptexture = NULL;
10004 rsurface.uselightmaptexture = false;
10005 for (;j < endsurface;j++)
10007 surface = rsurface.modelsurfaces + surfacelist[j];
10008 if (texture != surface->texture)
10010 texturesurfacelist[texturenumsurfaces++] = surface;
10015 rsurface.lightmaptexture = surface->lightmaptexture;
10016 rsurface.deluxemaptexture = surface->deluxemaptexture;
10017 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10018 for (;j < endsurface;j++)
10020 surface = rsurface.modelsurfaces + surfacelist[j];
10021 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10023 texturesurfacelist[texturenumsurfaces++] = surface;
10026 // render the range of surfaces
10027 if (ent == r_refdef.scene.worldentity)
10028 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10030 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10032 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10035 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10037 // transparent surfaces get pushed off into the transparent queue
10038 int surfacelistindex;
10039 const msurface_t *surface;
10040 vec3_t tempcenter, center;
10041 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10043 surface = texturesurfacelist[surfacelistindex];
10044 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10045 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10046 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10047 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10048 if (queueentity->transparent_offset) // transparent offset
10050 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10051 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10052 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10054 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10058 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10060 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10062 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10064 RSurf_SetupDepthAndCulling();
10065 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10066 if (rsurface.batchvertex3fbuffer)
10067 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10069 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10073 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10075 const entity_render_t *queueentity = r_refdef.scene.worldentity;
10078 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10081 if (!rsurface.texture->currentnumlayers)
10083 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10084 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10086 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10088 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10089 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10090 else if (!rsurface.texture->currentnumlayers)
10092 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10094 // in the deferred case, transparent surfaces were queued during prepass
10095 if (!r_shadow_usingdeferredprepass)
10096 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10100 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10101 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10106 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10109 texture_t *texture;
10110 R_FrameData_SetMark();
10111 // break the surface list down into batches by texture and use of lightmapping
10112 for (i = 0;i < numsurfaces;i = j)
10115 // texture is the base texture pointer, rsurface.texture is the
10116 // current frame/skin the texture is directing us to use (for example
10117 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10118 // use skin 1 instead)
10119 texture = surfacelist[i]->texture;
10120 rsurface.texture = R_GetCurrentTexture(texture);
10121 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10123 // if this texture is not the kind we want, skip ahead to the next one
10124 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10128 if(FAKELIGHT_ENABLED || depthonly || prepass)
10130 rsurface.lightmaptexture = NULL;
10131 rsurface.deluxemaptexture = NULL;
10132 rsurface.uselightmaptexture = false;
10133 // simply scan ahead until we find a different texture or lightmap state
10134 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10139 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10140 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10141 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10142 // simply scan ahead until we find a different texture or lightmap state
10143 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10146 // render the range of surfaces
10147 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10149 R_FrameData_ReturnToMark();
10152 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10156 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10159 if (!rsurface.texture->currentnumlayers)
10161 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10162 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10164 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10166 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10167 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10168 else if (!rsurface.texture->currentnumlayers)
10170 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10172 // in the deferred case, transparent surfaces were queued during prepass
10173 if (!r_shadow_usingdeferredprepass)
10174 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10178 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10179 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10184 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10187 texture_t *texture;
10188 R_FrameData_SetMark();
10189 // break the surface list down into batches by texture and use of lightmapping
10190 for (i = 0;i < numsurfaces;i = j)
10193 // texture is the base texture pointer, rsurface.texture is the
10194 // current frame/skin the texture is directing us to use (for example
10195 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10196 // use skin 1 instead)
10197 texture = surfacelist[i]->texture;
10198 rsurface.texture = R_GetCurrentTexture(texture);
10199 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10201 // if this texture is not the kind we want, skip ahead to the next one
10202 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10206 if(FAKELIGHT_ENABLED || depthonly || prepass)
10208 rsurface.lightmaptexture = NULL;
10209 rsurface.deluxemaptexture = NULL;
10210 rsurface.uselightmaptexture = false;
10211 // simply scan ahead until we find a different texture or lightmap state
10212 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10217 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10218 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10219 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10220 // simply scan ahead until we find a different texture or lightmap state
10221 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10224 // render the range of surfaces
10225 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10227 R_FrameData_ReturnToMark();
10230 float locboxvertex3f[6*4*3] =
10232 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10233 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10234 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10235 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10236 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10237 1,0,0, 0,0,0, 0,1,0, 1,1,0
10240 unsigned short locboxelements[6*2*3] =
10245 12,13,14, 12,14,15,
10246 16,17,18, 16,18,19,
10250 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10253 cl_locnode_t *loc = (cl_locnode_t *)ent;
10255 float vertex3f[6*4*3];
10257 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10258 GL_DepthMask(false);
10259 GL_DepthRange(0, 1);
10260 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10261 GL_DepthTest(true);
10262 GL_CullFace(GL_NONE);
10263 R_EntityMatrix(&identitymatrix);
10265 // R_Mesh_ResetTextureState();
10267 i = surfacelist[0];
10268 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10269 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10270 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10271 surfacelist[0] < 0 ? 0.5f : 0.125f);
10273 if (VectorCompare(loc->mins, loc->maxs))
10275 VectorSet(size, 2, 2, 2);
10276 VectorMA(loc->mins, -0.5f, size, mins);
10280 VectorCopy(loc->mins, mins);
10281 VectorSubtract(loc->maxs, loc->mins, size);
10284 for (i = 0;i < 6*4*3;)
10285 for (j = 0;j < 3;j++, i++)
10286 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10288 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10289 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10290 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10293 void R_DrawLocs(void)
10296 cl_locnode_t *loc, *nearestloc;
10298 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10299 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10301 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10302 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10306 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10308 if (decalsystem->decals)
10309 Mem_Free(decalsystem->decals);
10310 memset(decalsystem, 0, sizeof(*decalsystem));
10313 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)
10316 tridecal_t *decals;
10319 // expand or initialize the system
10320 if (decalsystem->maxdecals <= decalsystem->numdecals)
10322 decalsystem_t old = *decalsystem;
10323 qboolean useshortelements;
10324 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10325 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10326 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)));
10327 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10328 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10329 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10330 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10331 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10332 if (decalsystem->numdecals)
10333 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10335 Mem_Free(old.decals);
10336 for (i = 0;i < decalsystem->maxdecals*3;i++)
10337 decalsystem->element3i[i] = i;
10338 if (useshortelements)
10339 for (i = 0;i < decalsystem->maxdecals*3;i++)
10340 decalsystem->element3s[i] = i;
10343 // grab a decal and search for another free slot for the next one
10344 decals = decalsystem->decals;
10345 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10346 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10348 decalsystem->freedecal = i;
10349 if (decalsystem->numdecals <= i)
10350 decalsystem->numdecals = i + 1;
10352 // initialize the decal
10354 decal->triangleindex = triangleindex;
10355 decal->surfaceindex = surfaceindex;
10356 decal->decalsequence = decalsequence;
10357 decal->color4f[0][0] = c0[0];
10358 decal->color4f[0][1] = c0[1];
10359 decal->color4f[0][2] = c0[2];
10360 decal->color4f[0][3] = 1;
10361 decal->color4f[1][0] = c1[0];
10362 decal->color4f[1][1] = c1[1];
10363 decal->color4f[1][2] = c1[2];
10364 decal->color4f[1][3] = 1;
10365 decal->color4f[2][0] = c2[0];
10366 decal->color4f[2][1] = c2[1];
10367 decal->color4f[2][2] = c2[2];
10368 decal->color4f[2][3] = 1;
10369 decal->vertex3f[0][0] = v0[0];
10370 decal->vertex3f[0][1] = v0[1];
10371 decal->vertex3f[0][2] = v0[2];
10372 decal->vertex3f[1][0] = v1[0];
10373 decal->vertex3f[1][1] = v1[1];
10374 decal->vertex3f[1][2] = v1[2];
10375 decal->vertex3f[2][0] = v2[0];
10376 decal->vertex3f[2][1] = v2[1];
10377 decal->vertex3f[2][2] = v2[2];
10378 decal->texcoord2f[0][0] = t0[0];
10379 decal->texcoord2f[0][1] = t0[1];
10380 decal->texcoord2f[1][0] = t1[0];
10381 decal->texcoord2f[1][1] = t1[1];
10382 decal->texcoord2f[2][0] = t2[0];
10383 decal->texcoord2f[2][1] = t2[1];
10386 extern cvar_t cl_decals_bias;
10387 extern cvar_t cl_decals_models;
10388 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10389 // baseparms, parms, temps
10390 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)
10395 const float *vertex3f;
10396 const float *normal3f;
10398 float points[2][9][3];
10405 e = rsurface.modelelement3i + 3*triangleindex;
10407 vertex3f = rsurface.modelvertex3f;
10408 normal3f = rsurface.modelnormal3f;
10410 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10412 index = 3*e[cornerindex];
10413 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10416 //TriangleNormal(v[0], v[1], v[2], normal);
10417 //if (DotProduct(normal, localnormal) < 0.0f)
10419 // clip by each of the box planes formed from the projection matrix
10420 // if anything survives, we emit the decal
10421 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]);
10424 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]);
10427 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]);
10430 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]);
10433 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]);
10436 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]);
10439 // some part of the triangle survived, so we have to accept it...
10442 // dynamic always uses the original triangle
10444 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10446 index = 3*e[cornerindex];
10447 VectorCopy(vertex3f + index, v[cornerindex]);
10450 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10452 // convert vertex positions to texcoords
10453 Matrix4x4_Transform(projection, v[cornerindex], temp);
10454 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10455 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10456 // calculate distance fade from the projection origin
10457 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10458 f = bound(0.0f, f, 1.0f);
10459 c[cornerindex][0] = r * f;
10460 c[cornerindex][1] = g * f;
10461 c[cornerindex][2] = b * f;
10462 c[cornerindex][3] = 1.0f;
10463 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10466 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);
10468 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10469 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);
10471 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)
10473 matrix4x4_t projection;
10474 decalsystem_t *decalsystem;
10477 const msurface_t *surface;
10478 const msurface_t *surfaces;
10479 const int *surfacelist;
10480 const texture_t *texture;
10482 int numsurfacelist;
10483 int surfacelistindex;
10486 float localorigin[3];
10487 float localnormal[3];
10488 float localmins[3];
10489 float localmaxs[3];
10492 float planes[6][4];
10495 int bih_triangles_count;
10496 int bih_triangles[256];
10497 int bih_surfaces[256];
10499 decalsystem = &ent->decalsystem;
10500 model = ent->model;
10501 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10503 R_DecalSystem_Reset(&ent->decalsystem);
10507 if (!model->brush.data_leafs && !cl_decals_models.integer)
10509 if (decalsystem->model)
10510 R_DecalSystem_Reset(decalsystem);
10514 if (decalsystem->model != model)
10515 R_DecalSystem_Reset(decalsystem);
10516 decalsystem->model = model;
10518 RSurf_ActiveModelEntity(ent, true, false, false);
10520 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10521 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10522 VectorNormalize(localnormal);
10523 localsize = worldsize*rsurface.inversematrixscale;
10524 localmins[0] = localorigin[0] - localsize;
10525 localmins[1] = localorigin[1] - localsize;
10526 localmins[2] = localorigin[2] - localsize;
10527 localmaxs[0] = localorigin[0] + localsize;
10528 localmaxs[1] = localorigin[1] + localsize;
10529 localmaxs[2] = localorigin[2] + localsize;
10531 //VectorCopy(localnormal, planes[4]);
10532 //VectorVectors(planes[4], planes[2], planes[0]);
10533 AnglesFromVectors(angles, localnormal, NULL, false);
10534 AngleVectors(angles, planes[0], planes[2], planes[4]);
10535 VectorNegate(planes[0], planes[1]);
10536 VectorNegate(planes[2], planes[3]);
10537 VectorNegate(planes[4], planes[5]);
10538 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10539 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10540 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10541 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10542 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10543 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10548 matrix4x4_t forwardprojection;
10549 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10550 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10555 float projectionvector[4][3];
10556 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10557 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10558 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10559 projectionvector[0][0] = planes[0][0] * ilocalsize;
10560 projectionvector[0][1] = planes[1][0] * ilocalsize;
10561 projectionvector[0][2] = planes[2][0] * ilocalsize;
10562 projectionvector[1][0] = planes[0][1] * ilocalsize;
10563 projectionvector[1][1] = planes[1][1] * ilocalsize;
10564 projectionvector[1][2] = planes[2][1] * ilocalsize;
10565 projectionvector[2][0] = planes[0][2] * ilocalsize;
10566 projectionvector[2][1] = planes[1][2] * ilocalsize;
10567 projectionvector[2][2] = planes[2][2] * ilocalsize;
10568 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10569 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10570 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10571 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10575 dynamic = model->surfmesh.isanimated;
10576 numsurfacelist = model->nummodelsurfaces;
10577 surfacelist = model->sortedmodelsurfaces;
10578 surfaces = model->data_surfaces;
10581 bih_triangles_count = -1;
10584 if(model->render_bih.numleafs)
10585 bih = &model->render_bih;
10586 else if(model->collision_bih.numleafs)
10587 bih = &model->collision_bih;
10590 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10591 if(bih_triangles_count == 0)
10593 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10595 if(bih_triangles_count > 0)
10597 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10599 surfaceindex = bih_surfaces[triangleindex];
10600 surface = surfaces + surfaceindex;
10601 texture = surface->texture;
10602 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10604 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10606 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10611 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10613 surfaceindex = surfacelist[surfacelistindex];
10614 surface = surfaces + surfaceindex;
10615 // check cull box first because it rejects more than any other check
10616 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10618 // skip transparent surfaces
10619 texture = surface->texture;
10620 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10622 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10624 numtriangles = surface->num_triangles;
10625 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10626 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10631 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10632 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)
10634 int renderentityindex;
10635 float worldmins[3];
10636 float worldmaxs[3];
10637 entity_render_t *ent;
10639 if (!cl_decals_newsystem.integer)
10642 worldmins[0] = worldorigin[0] - worldsize;
10643 worldmins[1] = worldorigin[1] - worldsize;
10644 worldmins[2] = worldorigin[2] - worldsize;
10645 worldmaxs[0] = worldorigin[0] + worldsize;
10646 worldmaxs[1] = worldorigin[1] + worldsize;
10647 worldmaxs[2] = worldorigin[2] + worldsize;
10649 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10651 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10653 ent = r_refdef.scene.entities[renderentityindex];
10654 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10657 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10661 typedef struct r_decalsystem_splatqueue_s
10663 vec3_t worldorigin;
10664 vec3_t worldnormal;
10670 r_decalsystem_splatqueue_t;
10672 int r_decalsystem_numqueued = 0;
10673 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10675 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)
10677 r_decalsystem_splatqueue_t *queue;
10679 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10682 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10683 VectorCopy(worldorigin, queue->worldorigin);
10684 VectorCopy(worldnormal, queue->worldnormal);
10685 Vector4Set(queue->color, r, g, b, a);
10686 Vector4Set(queue->tcrange, s1, t1, s2, t2);
10687 queue->worldsize = worldsize;
10688 queue->decalsequence = cl.decalsequence++;
10691 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10694 r_decalsystem_splatqueue_t *queue;
10696 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10697 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);
10698 r_decalsystem_numqueued = 0;
10701 extern cvar_t cl_decals_max;
10702 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10705 decalsystem_t *decalsystem = &ent->decalsystem;
10712 if (!decalsystem->numdecals)
10715 if (r_showsurfaces.integer)
10718 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10720 R_DecalSystem_Reset(decalsystem);
10724 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10725 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10727 if (decalsystem->lastupdatetime)
10728 frametime = (cl.time - decalsystem->lastupdatetime);
10731 decalsystem->lastupdatetime = cl.time;
10732 decal = decalsystem->decals;
10733 numdecals = decalsystem->numdecals;
10735 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10737 if (decal->color4f[0][3])
10739 decal->lived += frametime;
10740 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10742 memset(decal, 0, sizeof(*decal));
10743 if (decalsystem->freedecal > i)
10744 decalsystem->freedecal = i;
10748 decal = decalsystem->decals;
10749 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10752 // collapse the array by shuffling the tail decals into the gaps
10755 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10756 decalsystem->freedecal++;
10757 if (decalsystem->freedecal == numdecals)
10759 decal[decalsystem->freedecal] = decal[--numdecals];
10762 decalsystem->numdecals = numdecals;
10764 if (numdecals <= 0)
10766 // if there are no decals left, reset decalsystem
10767 R_DecalSystem_Reset(decalsystem);
10771 extern skinframe_t *decalskinframe;
10772 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10775 decalsystem_t *decalsystem = &ent->decalsystem;
10784 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10787 numdecals = decalsystem->numdecals;
10791 if (r_showsurfaces.integer)
10794 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10796 R_DecalSystem_Reset(decalsystem);
10800 // if the model is static it doesn't matter what value we give for
10801 // wantnormals and wanttangents, so this logic uses only rules applicable
10802 // to a model, knowing that they are meaningless otherwise
10803 if (ent == r_refdef.scene.worldentity)
10804 RSurf_ActiveWorldEntity();
10806 RSurf_ActiveModelEntity(ent, false, false, false);
10808 decalsystem->lastupdatetime = cl.time;
10809 decal = decalsystem->decals;
10811 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10813 // update vertex positions for animated models
10814 v3f = decalsystem->vertex3f;
10815 c4f = decalsystem->color4f;
10816 t2f = decalsystem->texcoord2f;
10817 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10819 if (!decal->color4f[0][3])
10822 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10825 // update color values for fading decals
10826 if (decal->lived >= cl_decals_time.value)
10827 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10831 c4f[ 0] = decal->color4f[0][0] * alpha;
10832 c4f[ 1] = decal->color4f[0][1] * alpha;
10833 c4f[ 2] = decal->color4f[0][2] * alpha;
10835 c4f[ 4] = decal->color4f[1][0] * alpha;
10836 c4f[ 5] = decal->color4f[1][1] * alpha;
10837 c4f[ 6] = decal->color4f[1][2] * alpha;
10839 c4f[ 8] = decal->color4f[2][0] * alpha;
10840 c4f[ 9] = decal->color4f[2][1] * alpha;
10841 c4f[10] = decal->color4f[2][2] * alpha;
10844 t2f[0] = decal->texcoord2f[0][0];
10845 t2f[1] = decal->texcoord2f[0][1];
10846 t2f[2] = decal->texcoord2f[1][0];
10847 t2f[3] = decal->texcoord2f[1][1];
10848 t2f[4] = decal->texcoord2f[2][0];
10849 t2f[5] = decal->texcoord2f[2][1];
10851 // update vertex positions for animated models
10852 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10854 e = rsurface.modelelement3i + 3*decal->triangleindex;
10855 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10856 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10857 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10861 VectorCopy(decal->vertex3f[0], v3f);
10862 VectorCopy(decal->vertex3f[1], v3f + 3);
10863 VectorCopy(decal->vertex3f[2], v3f + 6);
10866 if (r_refdef.fogenabled)
10868 alpha = RSurf_FogVertex(v3f);
10869 VectorScale(c4f, alpha, c4f);
10870 alpha = RSurf_FogVertex(v3f + 3);
10871 VectorScale(c4f + 4, alpha, c4f + 4);
10872 alpha = RSurf_FogVertex(v3f + 6);
10873 VectorScale(c4f + 8, alpha, c4f + 8);
10884 r_refdef.stats.drawndecals += numtris;
10886 // now render the decals all at once
10887 // (this assumes they all use one particle font texture!)
10888 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);
10889 // R_Mesh_ResetTextureState();
10890 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10891 GL_DepthMask(false);
10892 GL_DepthRange(0, 1);
10893 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10894 GL_DepthTest(true);
10895 GL_CullFace(GL_NONE);
10896 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10897 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10898 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10902 static void R_DrawModelDecals(void)
10906 // fade faster when there are too many decals
10907 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10908 for (i = 0;i < r_refdef.scene.numentities;i++)
10909 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10911 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10912 for (i = 0;i < r_refdef.scene.numentities;i++)
10913 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10914 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10916 R_DecalSystem_ApplySplatEntitiesQueue();
10918 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10919 for (i = 0;i < r_refdef.scene.numentities;i++)
10920 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10922 r_refdef.stats.totaldecals += numdecals;
10924 if (r_showsurfaces.integer)
10927 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10929 for (i = 0;i < r_refdef.scene.numentities;i++)
10931 if (!r_refdef.viewcache.entityvisible[i])
10933 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10934 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10938 extern cvar_t mod_collision_bih;
10939 void R_DrawDebugModel(void)
10941 entity_render_t *ent = rsurface.entity;
10942 int i, j, k, l, flagsmask;
10943 const msurface_t *surface;
10944 dp_model_t *model = ent->model;
10947 switch(vid.renderpath)
10949 case RENDERPATH_GL11:
10950 case RENDERPATH_GL13:
10951 case RENDERPATH_GL20:
10953 case RENDERPATH_D3D9:
10954 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10956 case RENDERPATH_D3D10:
10957 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10959 case RENDERPATH_D3D11:
10960 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10962 case RENDERPATH_SOFT:
10963 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10965 case RENDERPATH_GLES2:
10966 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10970 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
10972 // R_Mesh_ResetTextureState();
10973 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10974 GL_DepthRange(0, 1);
10975 GL_DepthTest(!r_showdisabledepthtest.integer);
10976 GL_DepthMask(false);
10977 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10979 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
10983 qboolean cullbox = ent == r_refdef.scene.worldentity;
10984 const q3mbrush_t *brush;
10985 const bih_t *bih = &model->collision_bih;
10986 const bih_leaf_t *bihleaf;
10987 float vertex3f[3][3];
10988 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
10990 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
10992 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
10994 switch (bihleaf->type)
10997 brush = model->brush.data_brushes + bihleaf->itemindex;
10998 if (brush->colbrushf && brush->colbrushf->numtriangles)
11000 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);
11001 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11002 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11005 case BIH_COLLISIONTRIANGLE:
11006 triangleindex = bihleaf->itemindex;
11007 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11008 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11009 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11010 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);
11011 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11012 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11014 case BIH_RENDERTRIANGLE:
11015 triangleindex = bihleaf->itemindex;
11016 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11017 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11018 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11019 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);
11020 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11021 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11027 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11029 if (r_showtris.integer || (r_shownormals.value != 0))
11031 if (r_showdisabledepthtest.integer)
11033 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11034 GL_DepthMask(false);
11038 GL_BlendFunc(GL_ONE, GL_ZERO);
11039 GL_DepthMask(true);
11041 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11043 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11045 rsurface.texture = R_GetCurrentTexture(surface->texture);
11046 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11048 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11049 if (r_showtris.value > 0)
11051 if (!rsurface.texture->currentlayers->depthmask)
11052 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11053 else if (ent == r_refdef.scene.worldentity)
11054 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11056 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11057 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11058 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
11060 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
11063 if (r_shownormals.value < 0)
11065 qglBegin(GL_LINES);
11066 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11068 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11069 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11070 qglVertex3f(v[0], v[1], v[2]);
11071 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11072 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11073 qglVertex3f(v[0], v[1], v[2]);
11078 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11080 qglBegin(GL_LINES);
11081 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11083 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11084 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11085 qglVertex3f(v[0], v[1], v[2]);
11086 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11087 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11088 qglVertex3f(v[0], v[1], v[2]);
11092 qglBegin(GL_LINES);
11093 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11095 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11096 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11097 qglVertex3f(v[0], v[1], v[2]);
11098 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11099 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11100 qglVertex3f(v[0], v[1], v[2]);
11104 qglBegin(GL_LINES);
11105 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11107 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11108 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11109 qglVertex3f(v[0], v[1], v[2]);
11110 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11111 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11112 qglVertex3f(v[0], v[1], v[2]);
11119 rsurface.texture = NULL;
11123 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11124 int r_maxsurfacelist = 0;
11125 const msurface_t **r_surfacelist = NULL;
11126 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11128 int i, j, endj, flagsmask;
11129 dp_model_t *model = r_refdef.scene.worldmodel;
11130 msurface_t *surfaces;
11131 unsigned char *update;
11132 int numsurfacelist = 0;
11136 if (r_maxsurfacelist < model->num_surfaces)
11138 r_maxsurfacelist = model->num_surfaces;
11140 Mem_Free((msurface_t**)r_surfacelist);
11141 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11144 RSurf_ActiveWorldEntity();
11146 surfaces = model->data_surfaces;
11147 update = model->brushq1.lightmapupdateflags;
11149 // update light styles on this submodel
11150 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11152 model_brush_lightstyleinfo_t *style;
11153 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11155 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11157 int *list = style->surfacelist;
11158 style->value = r_refdef.scene.lightstylevalue[style->style];
11159 for (j = 0;j < style->numsurfaces;j++)
11160 update[list[j]] = true;
11165 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11169 R_DrawDebugModel();
11170 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11174 rsurface.lightmaptexture = NULL;
11175 rsurface.deluxemaptexture = NULL;
11176 rsurface.uselightmaptexture = false;
11177 rsurface.texture = NULL;
11178 rsurface.rtlight = NULL;
11179 numsurfacelist = 0;
11180 // add visible surfaces to draw list
11181 for (i = 0;i < model->nummodelsurfaces;i++)
11183 j = model->sortedmodelsurfaces[i];
11184 if (r_refdef.viewcache.world_surfacevisible[j])
11185 r_surfacelist[numsurfacelist++] = surfaces + j;
11187 // update lightmaps if needed
11188 if (model->brushq1.firstrender)
11190 model->brushq1.firstrender = false;
11191 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11193 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11197 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11198 if (r_refdef.viewcache.world_surfacevisible[j])
11200 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11202 // don't do anything if there were no surfaces
11203 if (!numsurfacelist)
11205 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11208 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11210 // add to stats if desired
11211 if (r_speeds.integer && !skysurfaces && !depthonly)
11213 r_refdef.stats.world_surfaces += numsurfacelist;
11214 for (j = 0;j < numsurfacelist;j++)
11215 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11218 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11221 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11223 int i, j, endj, flagsmask;
11224 dp_model_t *model = ent->model;
11225 msurface_t *surfaces;
11226 unsigned char *update;
11227 int numsurfacelist = 0;
11231 if (r_maxsurfacelist < model->num_surfaces)
11233 r_maxsurfacelist = model->num_surfaces;
11235 Mem_Free((msurface_t **)r_surfacelist);
11236 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11239 // if the model is static it doesn't matter what value we give for
11240 // wantnormals and wanttangents, so this logic uses only rules applicable
11241 // to a model, knowing that they are meaningless otherwise
11242 if (ent == r_refdef.scene.worldentity)
11243 RSurf_ActiveWorldEntity();
11244 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11245 RSurf_ActiveModelEntity(ent, false, false, false);
11247 RSurf_ActiveModelEntity(ent, true, true, true);
11248 else if (depthonly)
11250 switch (vid.renderpath)
11252 case RENDERPATH_GL20:
11253 case RENDERPATH_D3D9:
11254 case RENDERPATH_D3D10:
11255 case RENDERPATH_D3D11:
11256 case RENDERPATH_SOFT:
11257 case RENDERPATH_GLES2:
11258 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11260 case RENDERPATH_GL13:
11261 case RENDERPATH_GL11:
11262 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11268 switch (vid.renderpath)
11270 case RENDERPATH_GL20:
11271 case RENDERPATH_D3D9:
11272 case RENDERPATH_D3D10:
11273 case RENDERPATH_D3D11:
11274 case RENDERPATH_SOFT:
11275 case RENDERPATH_GLES2:
11276 RSurf_ActiveModelEntity(ent, true, true, false);
11278 case RENDERPATH_GL13:
11279 case RENDERPATH_GL11:
11280 RSurf_ActiveModelEntity(ent, true, false, false);
11285 surfaces = model->data_surfaces;
11286 update = model->brushq1.lightmapupdateflags;
11288 // update light styles
11289 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11291 model_brush_lightstyleinfo_t *style;
11292 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11294 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11296 int *list = style->surfacelist;
11297 style->value = r_refdef.scene.lightstylevalue[style->style];
11298 for (j = 0;j < style->numsurfaces;j++)
11299 update[list[j]] = true;
11304 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11308 R_DrawDebugModel();
11309 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11313 rsurface.lightmaptexture = NULL;
11314 rsurface.deluxemaptexture = NULL;
11315 rsurface.uselightmaptexture = false;
11316 rsurface.texture = NULL;
11317 rsurface.rtlight = NULL;
11318 numsurfacelist = 0;
11319 // add visible surfaces to draw list
11320 for (i = 0;i < model->nummodelsurfaces;i++)
11321 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11322 // don't do anything if there were no surfaces
11323 if (!numsurfacelist)
11325 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11328 // update lightmaps if needed
11332 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11337 R_BuildLightMap(ent, surfaces + j);
11342 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11344 R_BuildLightMap(ent, surfaces + j);
11345 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11347 // add to stats if desired
11348 if (r_speeds.integer && !skysurfaces && !depthonly)
11350 r_refdef.stats.entities_surfaces += numsurfacelist;
11351 for (j = 0;j < numsurfacelist;j++)
11352 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11355 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11358 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11360 static texture_t texture;
11361 static msurface_t surface;
11362 const msurface_t *surfacelist = &surface;
11364 // fake enough texture and surface state to render this geometry
11366 texture.update_lastrenderframe = -1; // regenerate this texture
11367 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11368 texture.currentskinframe = skinframe;
11369 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11370 texture.offsetmapping = OFFSETMAPPING_OFF;
11371 texture.offsetscale = 1;
11372 texture.specularscalemod = 1;
11373 texture.specularpowermod = 1;
11375 surface.texture = &texture;
11376 surface.num_triangles = numtriangles;
11377 surface.num_firsttriangle = firsttriangle;
11378 surface.num_vertices = numvertices;
11379 surface.num_firstvertex = firstvertex;
11382 rsurface.texture = R_GetCurrentTexture(surface.texture);
11383 rsurface.lightmaptexture = NULL;
11384 rsurface.deluxemaptexture = NULL;
11385 rsurface.uselightmaptexture = false;
11386 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11389 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)
11391 static msurface_t surface;
11392 const msurface_t *surfacelist = &surface;
11394 // fake enough texture and surface state to render this geometry
11395 surface.texture = texture;
11396 surface.num_triangles = numtriangles;
11397 surface.num_firsttriangle = firsttriangle;
11398 surface.num_vertices = numvertices;
11399 surface.num_firstvertex = firstvertex;
11402 rsurface.texture = R_GetCurrentTexture(surface.texture);
11403 rsurface.lightmaptexture = NULL;
11404 rsurface.deluxemaptexture = NULL;
11405 rsurface.uselightmaptexture = false;
11406 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);