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;
2543 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2544 switch(vid.renderpath)
2546 case RENDERPATH_D3D9:
2548 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);
2549 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2550 R_SetupShader_SetPermutationHLSL(mode, permutation);
2551 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2552 if (mode == SHADERMODE_LIGHTSOURCE)
2554 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2555 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2559 if (mode == SHADERMODE_LIGHTDIRECTION)
2561 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2564 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2565 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2566 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2567 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2568 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2570 if (mode == SHADERMODE_LIGHTSOURCE)
2572 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2573 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2574 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2575 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2576 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2578 // additive passes are only darkened by fog, not tinted
2579 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2580 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2584 if (mode == SHADERMODE_FLATCOLOR)
2586 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2588 else if (mode == SHADERMODE_LIGHTDIRECTION)
2590 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]);
2591 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2592 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);
2593 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);
2594 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2595 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2596 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2600 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2601 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2602 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);
2603 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);
2604 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2606 // additive passes are only darkened by fog, not tinted
2607 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2608 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2610 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2611 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);
2612 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2613 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2614 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2615 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2616 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2617 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2618 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2619 if (mode == SHADERMODE_WATER)
2620 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2622 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2623 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2624 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2625 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));
2626 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2627 if (rsurface.texture->pantstexture)
2628 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2630 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2631 if (rsurface.texture->shirttexture)
2632 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2634 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2635 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2636 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2637 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2638 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2639 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
2640 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2641 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2643 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2644 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2645 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2646 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2647 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2648 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2649 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2650 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2651 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2652 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2653 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2654 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2655 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2656 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2657 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2658 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2659 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2660 if (rsurfacepass == RSURFPASS_BACKGROUND)
2662 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2663 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2664 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2668 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2670 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2671 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2672 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2673 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2674 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2676 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2677 if (rsurface.rtlight)
2679 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2680 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2685 case RENDERPATH_D3D10:
2686 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2688 case RENDERPATH_D3D11:
2689 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2691 case RENDERPATH_GL20:
2692 case RENDERPATH_GLES2:
2693 if (!vid.useinterleavedarrays)
2695 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);
2696 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2697 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2698 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2699 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2700 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2701 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2702 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2706 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);
2707 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2709 R_SetupShader_SetPermutationGLSL(mode, permutation);
2710 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2711 if (mode == SHADERMODE_LIGHTSOURCE)
2713 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2714 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2715 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2716 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2717 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2718 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);
2720 // additive passes are only darkened by fog, not tinted
2721 if (r_glsl_permutation->loc_FogColor >= 0)
2722 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2723 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2727 if (mode == SHADERMODE_FLATCOLOR)
2729 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2731 else if (mode == SHADERMODE_LIGHTDIRECTION)
2733 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]);
2734 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]);
2735 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);
2736 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);
2737 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);
2738 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]);
2739 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]);
2743 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]);
2744 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]);
2745 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);
2746 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);
2747 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);
2749 // additive passes are only darkened by fog, not tinted
2750 if (r_glsl_permutation->loc_FogColor >= 0)
2752 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2753 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2755 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2757 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);
2758 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]);
2759 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]);
2760 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]);
2761 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]);
2762 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2763 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2764 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2765 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]);
2767 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2768 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2769 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2770 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]);
2771 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]);
2773 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2774 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));
2775 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2776 if (r_glsl_permutation->loc_Color_Pants >= 0)
2778 if (rsurface.texture->pantstexture)
2779 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2781 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2783 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2785 if (rsurface.texture->shirttexture)
2786 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2788 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2790 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]);
2791 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2792 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2793 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2794 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
2795 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]);
2796 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2797 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);}
2798 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity);
2800 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2801 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2802 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2803 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2804 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2805 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2806 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2807 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2808 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2809 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2810 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2811 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2812 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2813 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2814 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);
2815 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2816 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2817 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2818 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2819 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2820 if (rsurfacepass == RSURFPASS_BACKGROUND)
2822 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);
2823 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);
2824 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);
2828 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);
2830 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2831 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2832 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2833 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2834 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2836 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
2837 if (rsurface.rtlight)
2839 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2840 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2843 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2846 case RENDERPATH_GL13:
2847 case RENDERPATH_GL11:
2849 case RENDERPATH_SOFT:
2850 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);
2851 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2852 R_SetupShader_SetPermutationSoft(mode, permutation);
2853 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2854 if (mode == SHADERMODE_LIGHTSOURCE)
2856 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2857 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2858 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2859 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2860 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2861 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2863 // additive passes are only darkened by fog, not tinted
2864 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2865 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2869 if (mode == SHADERMODE_FLATCOLOR)
2871 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2873 else if (mode == SHADERMODE_LIGHTDIRECTION)
2875 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]);
2876 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2877 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);
2878 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);
2879 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2880 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]);
2881 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2885 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2886 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2887 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);
2888 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);
2889 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2891 // additive passes are only darkened by fog, not tinted
2892 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
2893 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2895 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2896 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);
2897 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2898 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2899 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]);
2900 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]);
2901 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2902 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2903 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2904 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2906 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2907 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2908 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2909 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2910 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]);
2912 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2913 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));
2914 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2915 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2917 if (rsurface.texture->pantstexture)
2918 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2920 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2922 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2924 if (rsurface.texture->shirttexture)
2925 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2927 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2929 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2930 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2931 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2932 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2933 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
2934 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2935 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2937 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2938 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2939 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2940 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2941 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2942 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2943 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2944 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2945 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2946 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2947 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2948 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2949 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2950 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2951 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2952 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2953 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2954 if (rsurfacepass == RSURFPASS_BACKGROUND)
2956 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2957 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2958 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2962 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2964 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2965 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2966 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2967 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2968 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2970 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2971 if (rsurface.rtlight)
2973 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2974 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2981 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2983 // select a permutation of the lighting shader appropriate to this
2984 // combination of texture, entity, light source, and fogging, only use the
2985 // minimum features necessary to avoid wasting rendering time in the
2986 // fragment shader on features that are not being used
2987 unsigned int permutation = 0;
2988 unsigned int mode = 0;
2989 const float *lightcolorbase = rtlight->currentcolor;
2990 float ambientscale = rtlight->ambientscale;
2991 float diffusescale = rtlight->diffusescale;
2992 float specularscale = rtlight->specularscale;
2993 // this is the location of the light in view space
2994 vec3_t viewlightorigin;
2995 // this transforms from view space (camera) to light space (cubemap)
2996 matrix4x4_t viewtolight;
2997 matrix4x4_t lighttoview;
2998 float viewtolight16f[16];
2999 float range = 1.0f / r_shadow_deferred_8bitrange.value;
3001 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3002 if (rtlight->currentcubemap != r_texture_whitecube)
3003 permutation |= SHADERPERMUTATION_CUBEFILTER;
3004 if (diffusescale > 0)
3005 permutation |= SHADERPERMUTATION_DIFFUSE;
3006 if (specularscale > 0)
3007 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3008 if (r_shadow_usingshadowmap2d)
3010 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3011 if (r_shadow_shadowmapvsdct)
3012 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3014 if (r_shadow_shadowmapsampler)
3015 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
3016 if (r_shadow_shadowmappcf > 1)
3017 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
3018 else if (r_shadow_shadowmappcf)
3019 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
3021 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3022 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3023 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3024 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3025 switch(vid.renderpath)
3027 case RENDERPATH_D3D9:
3029 R_SetupShader_SetPermutationHLSL(mode, permutation);
3030 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3031 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3032 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
3033 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
3034 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3035 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3036 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3037 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
3038 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3039 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3041 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3042 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
3043 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3044 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3045 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
3046 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3049 case RENDERPATH_D3D10:
3050 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3052 case RENDERPATH_D3D11:
3053 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3055 case RENDERPATH_GL20:
3056 case RENDERPATH_GLES2:
3057 R_SetupShader_SetPermutationGLSL(mode, permutation);
3058 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3059 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
3060 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);
3061 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);
3062 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);
3063 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]);
3064 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]);
3065 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));
3066 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]);
3067 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
3069 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
3070 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
3071 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
3072 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
3073 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
3074 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
3076 case RENDERPATH_GL13:
3077 case RENDERPATH_GL11:
3079 case RENDERPATH_SOFT:
3080 R_SetupShader_SetPermutationGLSL(mode, permutation);
3081 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3082 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
3083 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
3084 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
3085 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3086 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3087 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]);
3088 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));
3089 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3090 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3092 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3093 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
3094 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3095 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3096 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
3097 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3102 #define SKINFRAME_HASH 1024
3106 int loadsequence; // incremented each level change
3107 memexpandablearray_t array;
3108 skinframe_t *hash[SKINFRAME_HASH];
3111 r_skinframe_t r_skinframe;
3113 void R_SkinFrame_PrepareForPurge(void)
3115 r_skinframe.loadsequence++;
3116 // wrap it without hitting zero
3117 if (r_skinframe.loadsequence >= 200)
3118 r_skinframe.loadsequence = 1;
3121 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3125 // mark the skinframe as used for the purging code
3126 skinframe->loadsequence = r_skinframe.loadsequence;
3129 void R_SkinFrame_Purge(void)
3133 for (i = 0;i < SKINFRAME_HASH;i++)
3135 for (s = r_skinframe.hash[i];s;s = s->next)
3137 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3139 if (s->merged == s->base)
3141 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3142 R_PurgeTexture(s->stain );s->stain = NULL;
3143 R_PurgeTexture(s->merged);s->merged = NULL;
3144 R_PurgeTexture(s->base );s->base = NULL;
3145 R_PurgeTexture(s->pants );s->pants = NULL;
3146 R_PurgeTexture(s->shirt );s->shirt = NULL;
3147 R_PurgeTexture(s->nmap );s->nmap = NULL;
3148 R_PurgeTexture(s->gloss );s->gloss = NULL;
3149 R_PurgeTexture(s->glow );s->glow = NULL;
3150 R_PurgeTexture(s->fog );s->fog = NULL;
3151 R_PurgeTexture(s->reflect);s->reflect = NULL;
3152 s->loadsequence = 0;
3158 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3160 char basename[MAX_QPATH];
3162 Image_StripImageExtension(name, basename, sizeof(basename));
3164 if( last == NULL ) {
3166 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3167 item = r_skinframe.hash[hashindex];
3172 // linearly search through the hash bucket
3173 for( ; item ; item = item->next ) {
3174 if( !strcmp( item->basename, basename ) ) {
3181 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3185 char basename[MAX_QPATH];
3187 Image_StripImageExtension(name, basename, sizeof(basename));
3189 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3190 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3191 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3195 rtexture_t *dyntexture;
3196 // check whether its a dynamic texture
3197 dyntexture = CL_GetDynTexture( basename );
3198 if (!add && !dyntexture)
3200 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3201 memset(item, 0, sizeof(*item));
3202 strlcpy(item->basename, basename, sizeof(item->basename));
3203 item->base = dyntexture; // either NULL or dyntexture handle
3204 item->textureflags = textureflags;
3205 item->comparewidth = comparewidth;
3206 item->compareheight = compareheight;
3207 item->comparecrc = comparecrc;
3208 item->next = r_skinframe.hash[hashindex];
3209 r_skinframe.hash[hashindex] = item;
3211 else if( item->base == NULL )
3213 rtexture_t *dyntexture;
3214 // check whether its a dynamic texture
3215 // 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]
3216 dyntexture = CL_GetDynTexture( basename );
3217 item->base = dyntexture; // either NULL or dyntexture handle
3220 R_SkinFrame_MarkUsed(item);
3224 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3226 unsigned long long avgcolor[5], wsum; \
3234 for(pix = 0; pix < cnt; ++pix) \
3237 for(comp = 0; comp < 3; ++comp) \
3239 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3242 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3244 for(comp = 0; comp < 3; ++comp) \
3245 avgcolor[comp] += getpixel * w; \
3248 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3249 avgcolor[4] += getpixel; \
3251 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3253 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3254 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3255 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3256 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3259 extern cvar_t gl_picmip;
3260 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3263 unsigned char *pixels;
3264 unsigned char *bumppixels;
3265 unsigned char *basepixels = NULL;
3266 int basepixels_width = 0;
3267 int basepixels_height = 0;
3268 skinframe_t *skinframe;
3269 rtexture_t *ddsbase = NULL;
3270 qboolean ddshasalpha = false;
3271 float ddsavgcolor[4];
3272 char basename[MAX_QPATH];
3273 int miplevel = R_PicmipForFlags(textureflags);
3274 int savemiplevel = miplevel;
3277 if (cls.state == ca_dedicated)
3280 // return an existing skinframe if already loaded
3281 // if loading of the first image fails, don't make a new skinframe as it
3282 // would cause all future lookups of this to be missing
3283 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3284 if (skinframe && skinframe->base)
3287 Image_StripImageExtension(name, basename, sizeof(basename));
3289 // check for DDS texture file first
3290 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3292 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
3293 if (basepixels == NULL)
3297 // FIXME handle miplevel
3299 if (developer_loading.integer)
3300 Con_Printf("loading skin \"%s\"\n", name);
3302 // we've got some pixels to store, so really allocate this new texture now
3304 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3305 skinframe->stain = NULL;
3306 skinframe->merged = NULL;
3307 skinframe->base = NULL;
3308 skinframe->pants = NULL;
3309 skinframe->shirt = NULL;
3310 skinframe->nmap = NULL;
3311 skinframe->gloss = NULL;
3312 skinframe->glow = NULL;
3313 skinframe->fog = NULL;
3314 skinframe->reflect = NULL;
3315 skinframe->hasalpha = false;
3319 skinframe->base = ddsbase;
3320 skinframe->hasalpha = ddshasalpha;
3321 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3322 if (r_loadfog && skinframe->hasalpha)
3323 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3324 //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]);
3328 basepixels_width = image_width;
3329 basepixels_height = image_height;
3330 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);
3331 if (textureflags & TEXF_ALPHA)
3333 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3335 if (basepixels[j] < 255)
3337 skinframe->hasalpha = true;
3341 if (r_loadfog && skinframe->hasalpha)
3343 // has transparent pixels
3344 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3345 for (j = 0;j < image_width * image_height * 4;j += 4)
3350 pixels[j+3] = basepixels[j+3];
3352 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);
3356 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3357 //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]);
3358 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3359 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
3360 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3361 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
3366 mymiplevel = savemiplevel;
3367 if (r_loadnormalmap)
3368 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);
3369 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3371 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3372 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3373 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3374 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3377 // _norm is the name used by tenebrae and has been adopted as standard
3378 if (r_loadnormalmap && skinframe->nmap == NULL)
3380 mymiplevel = savemiplevel;
3381 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3383 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);
3387 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3389 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3390 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3391 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);
3393 Mem_Free(bumppixels);
3395 else if (r_shadow_bumpscale_basetexture.value > 0)
3397 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3398 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3399 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);
3402 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3403 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
3406 // _luma is supported only for tenebrae compatibility
3407 // _glow is the preferred name
3408 mymiplevel = savemiplevel;
3409 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))))
3411 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);
3412 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3413 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
3414 Mem_Free(pixels);pixels = NULL;
3417 mymiplevel = savemiplevel;
3418 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3420 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);
3421 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3422 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
3427 mymiplevel = savemiplevel;
3428 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3430 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);
3431 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3432 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
3437 mymiplevel = savemiplevel;
3438 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3440 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);
3441 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3442 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
3447 mymiplevel = savemiplevel;
3448 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3450 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);
3451 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3452 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
3458 Mem_Free(basepixels);
3463 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3464 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
3467 unsigned char *temp1, *temp2;
3468 skinframe_t *skinframe;
3470 if (cls.state == ca_dedicated)
3473 // if already loaded just return it, otherwise make a new skinframe
3474 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3475 if (skinframe && skinframe->base)
3478 skinframe->stain = NULL;
3479 skinframe->merged = NULL;
3480 skinframe->base = NULL;
3481 skinframe->pants = NULL;
3482 skinframe->shirt = NULL;
3483 skinframe->nmap = NULL;
3484 skinframe->gloss = NULL;
3485 skinframe->glow = NULL;
3486 skinframe->fog = NULL;
3487 skinframe->reflect = NULL;
3488 skinframe->hasalpha = false;
3490 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3494 if (developer_loading.integer)
3495 Con_Printf("loading 32bit skin \"%s\"\n", name);
3497 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3499 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3500 temp2 = temp1 + width * height * 4;
3501 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3502 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);
3505 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
3506 if (textureflags & TEXF_ALPHA)
3508 for (i = 3;i < width * height * 4;i += 4)
3510 if (skindata[i] < 255)
3512 skinframe->hasalpha = true;
3516 if (r_loadfog && skinframe->hasalpha)
3518 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3519 memcpy(fogpixels, skindata, width * height * 4);
3520 for (i = 0;i < width * height * 4;i += 4)
3521 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3522 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3523 Mem_Free(fogpixels);
3527 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3528 //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]);
3533 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3537 skinframe_t *skinframe;
3539 if (cls.state == ca_dedicated)
3542 // if already loaded just return it, otherwise make a new skinframe
3543 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3544 if (skinframe && skinframe->base)
3547 skinframe->stain = NULL;
3548 skinframe->merged = NULL;
3549 skinframe->base = NULL;
3550 skinframe->pants = NULL;
3551 skinframe->shirt = NULL;
3552 skinframe->nmap = NULL;
3553 skinframe->gloss = NULL;
3554 skinframe->glow = NULL;
3555 skinframe->fog = NULL;
3556 skinframe->reflect = NULL;
3557 skinframe->hasalpha = false;
3559 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3563 if (developer_loading.integer)
3564 Con_Printf("loading quake skin \"%s\"\n", name);
3566 // 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)
3567 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3568 memcpy(skinframe->qpixels, skindata, width*height);
3569 skinframe->qwidth = width;
3570 skinframe->qheight = height;
3573 for (i = 0;i < width * height;i++)
3574 featuresmask |= palette_featureflags[skindata[i]];
3576 skinframe->hasalpha = false;
3577 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3578 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3579 skinframe->qgeneratemerged = true;
3580 skinframe->qgeneratebase = skinframe->qhascolormapping;
3581 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3583 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3584 //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]);
3589 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3593 unsigned char *skindata;
3595 if (!skinframe->qpixels)
3598 if (!skinframe->qhascolormapping)
3599 colormapped = false;
3603 if (!skinframe->qgeneratebase)
3608 if (!skinframe->qgeneratemerged)
3612 width = skinframe->qwidth;
3613 height = skinframe->qheight;
3614 skindata = skinframe->qpixels;
3616 if (skinframe->qgeneratenmap)
3618 unsigned char *temp1, *temp2;
3619 skinframe->qgeneratenmap = false;
3620 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3621 temp2 = temp1 + width * height * 4;
3622 // use either a custom palette or the quake palette
3623 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3624 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3625 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);
3629 if (skinframe->qgenerateglow)
3631 skinframe->qgenerateglow = false;
3632 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3637 skinframe->qgeneratebase = false;
3638 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);
3639 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3640 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3644 skinframe->qgeneratemerged = false;
3645 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);
3648 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3650 Mem_Free(skinframe->qpixels);
3651 skinframe->qpixels = NULL;
3655 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)
3658 skinframe_t *skinframe;
3660 if (cls.state == ca_dedicated)
3663 // if already loaded just return it, otherwise make a new skinframe
3664 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3665 if (skinframe && skinframe->base)
3668 skinframe->stain = NULL;
3669 skinframe->merged = NULL;
3670 skinframe->base = NULL;
3671 skinframe->pants = NULL;
3672 skinframe->shirt = NULL;
3673 skinframe->nmap = NULL;
3674 skinframe->gloss = NULL;
3675 skinframe->glow = NULL;
3676 skinframe->fog = NULL;
3677 skinframe->reflect = NULL;
3678 skinframe->hasalpha = false;
3680 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3684 if (developer_loading.integer)
3685 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3687 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3688 if (textureflags & TEXF_ALPHA)
3690 for (i = 0;i < width * height;i++)
3692 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3694 skinframe->hasalpha = true;
3698 if (r_loadfog && skinframe->hasalpha)
3699 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3702 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3703 //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]);
3708 skinframe_t *R_SkinFrame_LoadMissing(void)
3710 skinframe_t *skinframe;
3712 if (cls.state == ca_dedicated)
3715 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3716 skinframe->stain = NULL;
3717 skinframe->merged = NULL;
3718 skinframe->base = NULL;
3719 skinframe->pants = NULL;
3720 skinframe->shirt = NULL;
3721 skinframe->nmap = NULL;
3722 skinframe->gloss = NULL;
3723 skinframe->glow = NULL;
3724 skinframe->fog = NULL;
3725 skinframe->reflect = NULL;
3726 skinframe->hasalpha = false;
3728 skinframe->avgcolor[0] = rand() / RAND_MAX;
3729 skinframe->avgcolor[1] = rand() / RAND_MAX;
3730 skinframe->avgcolor[2] = rand() / RAND_MAX;
3731 skinframe->avgcolor[3] = 1;
3736 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3737 typedef struct suffixinfo_s
3740 qboolean flipx, flipy, flipdiagonal;
3743 static suffixinfo_t suffix[3][6] =
3746 {"px", false, false, false},
3747 {"nx", false, false, false},
3748 {"py", false, false, false},
3749 {"ny", false, false, false},
3750 {"pz", false, false, false},
3751 {"nz", false, false, false}
3754 {"posx", false, false, false},
3755 {"negx", false, false, false},
3756 {"posy", false, false, false},
3757 {"negy", false, false, false},
3758 {"posz", false, false, false},
3759 {"negz", false, false, false}
3762 {"rt", true, false, true},
3763 {"lf", false, true, true},
3764 {"ft", true, true, false},
3765 {"bk", false, false, false},
3766 {"up", true, false, true},
3767 {"dn", true, false, true}
3771 static int componentorder[4] = {0, 1, 2, 3};
3773 rtexture_t *R_LoadCubemap(const char *basename)
3775 int i, j, cubemapsize;
3776 unsigned char *cubemappixels, *image_buffer;
3777 rtexture_t *cubemaptexture;
3779 // must start 0 so the first loadimagepixels has no requested width/height
3781 cubemappixels = NULL;
3782 cubemaptexture = NULL;
3783 // keep trying different suffix groups (posx, px, rt) until one loads
3784 for (j = 0;j < 3 && !cubemappixels;j++)
3786 // load the 6 images in the suffix group
3787 for (i = 0;i < 6;i++)
3789 // generate an image name based on the base and and suffix
3790 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3792 if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
3794 // an image loaded, make sure width and height are equal
3795 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3797 // if this is the first image to load successfully, allocate the cubemap memory
3798 if (!cubemappixels && image_width >= 1)
3800 cubemapsize = image_width;
3801 // note this clears to black, so unavailable sides are black
3802 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3804 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3806 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);
3809 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3811 Mem_Free(image_buffer);
3815 // if a cubemap loaded, upload it
3818 if (developer_loading.integer)
3819 Con_Printf("loading cubemap \"%s\"\n", basename);
3821 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3822 Mem_Free(cubemappixels);
3826 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3827 if (developer_loading.integer)
3829 Con_Printf("(tried tried images ");
3830 for (j = 0;j < 3;j++)
3831 for (i = 0;i < 6;i++)
3832 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3833 Con_Print(" and was unable to find any of them).\n");
3836 return cubemaptexture;
3839 rtexture_t *R_GetCubemap(const char *basename)
3842 for (i = 0;i < r_texture_numcubemaps;i++)
3843 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3844 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3845 if (i >= MAX_CUBEMAPS)
3846 return r_texture_whitecube;
3847 r_texture_numcubemaps++;
3848 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3849 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3850 return r_texture_cubemaps[i].texture;
3853 void R_FreeCubemaps(void)
3856 for (i = 0;i < r_texture_numcubemaps;i++)
3858 if (developer_loading.integer)
3859 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3860 if (r_texture_cubemaps[i].texture)
3861 R_FreeTexture(r_texture_cubemaps[i].texture);
3863 r_texture_numcubemaps = 0;
3866 void R_Main_FreeViewCache(void)
3868 if (r_refdef.viewcache.entityvisible)
3869 Mem_Free(r_refdef.viewcache.entityvisible);
3870 if (r_refdef.viewcache.world_pvsbits)
3871 Mem_Free(r_refdef.viewcache.world_pvsbits);
3872 if (r_refdef.viewcache.world_leafvisible)
3873 Mem_Free(r_refdef.viewcache.world_leafvisible);
3874 if (r_refdef.viewcache.world_surfacevisible)
3875 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3876 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3879 void R_Main_ResizeViewCache(void)
3881 int numentities = r_refdef.scene.numentities;
3882 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3883 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3884 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3885 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3886 if (r_refdef.viewcache.maxentities < numentities)
3888 r_refdef.viewcache.maxentities = numentities;
3889 if (r_refdef.viewcache.entityvisible)
3890 Mem_Free(r_refdef.viewcache.entityvisible);
3891 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3893 if (r_refdef.viewcache.world_numclusters != numclusters)
3895 r_refdef.viewcache.world_numclusters = numclusters;
3896 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3897 if (r_refdef.viewcache.world_pvsbits)
3898 Mem_Free(r_refdef.viewcache.world_pvsbits);
3899 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3901 if (r_refdef.viewcache.world_numleafs != numleafs)
3903 r_refdef.viewcache.world_numleafs = numleafs;
3904 if (r_refdef.viewcache.world_leafvisible)
3905 Mem_Free(r_refdef.viewcache.world_leafvisible);
3906 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3908 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3910 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3911 if (r_refdef.viewcache.world_surfacevisible)
3912 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3913 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3917 extern rtexture_t *loadingscreentexture;
3918 void gl_main_start(void)
3920 loadingscreentexture = NULL;
3921 r_texture_blanknormalmap = NULL;
3922 r_texture_white = NULL;
3923 r_texture_grey128 = NULL;
3924 r_texture_black = NULL;
3925 r_texture_whitecube = NULL;
3926 r_texture_normalizationcube = NULL;
3927 r_texture_fogattenuation = NULL;
3928 r_texture_fogheighttexture = NULL;
3929 r_texture_gammaramps = NULL;
3930 r_texture_numcubemaps = 0;
3932 r_loaddds = r_texture_dds_load.integer != 0;
3933 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3935 switch(vid.renderpath)
3937 case RENDERPATH_GL20:
3938 case RENDERPATH_D3D9:
3939 case RENDERPATH_D3D10:
3940 case RENDERPATH_D3D11:
3941 case RENDERPATH_SOFT:
3942 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3943 Cvar_SetValueQuick(&gl_combine, 1);
3944 Cvar_SetValueQuick(&r_glsl, 1);
3945 r_loadnormalmap = true;
3949 case RENDERPATH_GL13:
3950 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3951 Cvar_SetValueQuick(&gl_combine, 1);
3952 Cvar_SetValueQuick(&r_glsl, 0);
3953 r_loadnormalmap = false;
3954 r_loadgloss = false;
3957 case RENDERPATH_GL11:
3958 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3959 Cvar_SetValueQuick(&gl_combine, 0);
3960 Cvar_SetValueQuick(&r_glsl, 0);
3961 r_loadnormalmap = false;
3962 r_loadgloss = false;
3965 case RENDERPATH_GLES2:
3966 Cvar_SetValueQuick(&r_textureunits, 1);
3967 Cvar_SetValueQuick(&gl_combine, 1);
3968 Cvar_SetValueQuick(&r_glsl, 1);
3969 r_loadnormalmap = true;
3970 r_loadgloss = false;
3976 R_FrameData_Reset();
3980 memset(r_queries, 0, sizeof(r_queries));
3982 r_qwskincache = NULL;
3983 r_qwskincache_size = 0;
3985 // set up r_skinframe loading system for textures
3986 memset(&r_skinframe, 0, sizeof(r_skinframe));
3987 r_skinframe.loadsequence = 1;
3988 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3990 r_main_texturepool = R_AllocTexturePool();
3991 R_BuildBlankTextures();
3993 if (vid.support.arb_texture_cube_map)
3996 R_BuildNormalizationCube();
3998 r_texture_fogattenuation = NULL;
3999 r_texture_fogheighttexture = NULL;
4000 r_texture_gammaramps = NULL;
4001 //r_texture_fogintensity = NULL;
4002 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4003 memset(&r_waterstate, 0, sizeof(r_waterstate));
4004 r_glsl_permutation = NULL;
4005 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4006 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4007 glslshaderstring = NULL;
4009 r_hlsl_permutation = NULL;
4010 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4011 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4013 hlslshaderstring = NULL;
4014 memset(&r_svbsp, 0, sizeof (r_svbsp));
4016 r_refdef.fogmasktable_density = 0;
4019 void gl_main_shutdown(void)
4022 R_FrameData_Reset();
4024 R_Main_FreeViewCache();
4026 switch(vid.renderpath)
4028 case RENDERPATH_GL11:
4029 case RENDERPATH_GL13:
4030 case RENDERPATH_GL20:
4031 case RENDERPATH_GLES2:
4033 qglDeleteQueriesARB(r_maxqueries, r_queries);
4035 case RENDERPATH_D3D9:
4036 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4038 case RENDERPATH_D3D10:
4039 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4041 case RENDERPATH_D3D11:
4042 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4044 case RENDERPATH_SOFT:
4050 memset(r_queries, 0, sizeof(r_queries));
4052 r_qwskincache = NULL;
4053 r_qwskincache_size = 0;
4055 // clear out the r_skinframe state
4056 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4057 memset(&r_skinframe, 0, sizeof(r_skinframe));
4060 Mem_Free(r_svbsp.nodes);
4061 memset(&r_svbsp, 0, sizeof (r_svbsp));
4062 R_FreeTexturePool(&r_main_texturepool);
4063 loadingscreentexture = NULL;
4064 r_texture_blanknormalmap = NULL;
4065 r_texture_white = NULL;
4066 r_texture_grey128 = NULL;
4067 r_texture_black = NULL;
4068 r_texture_whitecube = NULL;
4069 r_texture_normalizationcube = NULL;
4070 r_texture_fogattenuation = NULL;
4071 r_texture_fogheighttexture = NULL;
4072 r_texture_gammaramps = NULL;
4073 r_texture_numcubemaps = 0;
4074 //r_texture_fogintensity = NULL;
4075 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4076 memset(&r_waterstate, 0, sizeof(r_waterstate));
4079 r_glsl_permutation = NULL;
4080 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4081 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4082 glslshaderstring = NULL;
4084 r_hlsl_permutation = NULL;
4085 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4086 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4088 hlslshaderstring = NULL;
4091 extern void CL_ParseEntityLump(char *entitystring);
4092 void gl_main_newmap(void)
4094 // FIXME: move this code to client
4095 char *entities, entname[MAX_QPATH];
4097 Mem_Free(r_qwskincache);
4098 r_qwskincache = NULL;
4099 r_qwskincache_size = 0;
4102 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4103 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4105 CL_ParseEntityLump(entities);
4109 if (cl.worldmodel->brush.entities)
4110 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4112 R_Main_FreeViewCache();
4114 R_FrameData_Reset();
4117 void GL_Main_Init(void)
4119 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4121 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4122 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4123 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4124 if (gamemode == GAME_NEHAHRA)
4126 Cvar_RegisterVariable (&gl_fogenable);
4127 Cvar_RegisterVariable (&gl_fogdensity);
4128 Cvar_RegisterVariable (&gl_fogred);
4129 Cvar_RegisterVariable (&gl_foggreen);
4130 Cvar_RegisterVariable (&gl_fogblue);
4131 Cvar_RegisterVariable (&gl_fogstart);
4132 Cvar_RegisterVariable (&gl_fogend);
4133 Cvar_RegisterVariable (&gl_skyclip);
4135 Cvar_RegisterVariable(&r_motionblur);
4136 Cvar_RegisterVariable(&r_motionblur_maxblur);
4137 Cvar_RegisterVariable(&r_motionblur_bmin);
4138 Cvar_RegisterVariable(&r_motionblur_vmin);
4139 Cvar_RegisterVariable(&r_motionblur_vmax);
4140 Cvar_RegisterVariable(&r_motionblur_vcoeff);
4141 Cvar_RegisterVariable(&r_motionblur_randomize);
4142 Cvar_RegisterVariable(&r_damageblur);
4143 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4144 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4145 Cvar_RegisterVariable(&r_equalize_entities_by);
4146 Cvar_RegisterVariable(&r_equalize_entities_to);
4147 Cvar_RegisterVariable(&r_depthfirst);
4148 Cvar_RegisterVariable(&r_useinfinitefarclip);
4149 Cvar_RegisterVariable(&r_farclip_base);
4150 Cvar_RegisterVariable(&r_farclip_world);
4151 Cvar_RegisterVariable(&r_nearclip);
4152 Cvar_RegisterVariable(&r_showbboxes);
4153 Cvar_RegisterVariable(&r_showsurfaces);
4154 Cvar_RegisterVariable(&r_showtris);
4155 Cvar_RegisterVariable(&r_shownormals);
4156 Cvar_RegisterVariable(&r_showlighting);
4157 Cvar_RegisterVariable(&r_showshadowvolumes);
4158 Cvar_RegisterVariable(&r_showcollisionbrushes);
4159 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4160 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4161 Cvar_RegisterVariable(&r_showdisabledepthtest);
4162 Cvar_RegisterVariable(&r_drawportals);
4163 Cvar_RegisterVariable(&r_drawentities);
4164 Cvar_RegisterVariable(&r_draw2d);
4165 Cvar_RegisterVariable(&r_drawworld);
4166 Cvar_RegisterVariable(&r_cullentities_trace);
4167 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4168 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4169 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4170 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4171 Cvar_RegisterVariable(&r_drawviewmodel);
4172 Cvar_RegisterVariable(&r_drawexteriormodel);
4173 Cvar_RegisterVariable(&r_speeds);
4174 Cvar_RegisterVariable(&r_fullbrights);
4175 Cvar_RegisterVariable(&r_wateralpha);
4176 Cvar_RegisterVariable(&r_dynamic);
4177 Cvar_RegisterVariable(&r_fakelight);
4178 Cvar_RegisterVariable(&r_fakelight_intensity);
4179 Cvar_RegisterVariable(&r_fullbright);
4180 Cvar_RegisterVariable(&r_shadows);
4181 Cvar_RegisterVariable(&r_shadows_darken);
4182 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4183 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4184 Cvar_RegisterVariable(&r_shadows_throwdistance);
4185 Cvar_RegisterVariable(&r_shadows_throwdirection);
4186 Cvar_RegisterVariable(&r_shadows_focus);
4187 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4188 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4189 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4190 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4191 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4192 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4193 Cvar_RegisterVariable(&r_fog_exp2);
4194 Cvar_RegisterVariable(&r_drawfog);
4195 Cvar_RegisterVariable(&r_transparentdepthmasking);
4196 Cvar_RegisterVariable(&r_texture_dds_load);
4197 Cvar_RegisterVariable(&r_texture_dds_save);
4198 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
4199 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
4200 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
4201 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
4202 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
4203 Cvar_RegisterVariable(&r_textureunits);
4204 Cvar_RegisterVariable(&gl_combine);
4205 Cvar_RegisterVariable(&r_glsl);
4206 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4207 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4208 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4209 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4210 Cvar_RegisterVariable(&r_glsl_postprocess);
4211 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4212 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4213 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4214 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4215 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4216 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4217 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4218 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4220 Cvar_RegisterVariable(&r_water);
4221 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4222 Cvar_RegisterVariable(&r_water_clippingplanebias);
4223 Cvar_RegisterVariable(&r_water_refractdistort);
4224 Cvar_RegisterVariable(&r_water_reflectdistort);
4225 Cvar_RegisterVariable(&r_water_scissormode);
4226 Cvar_RegisterVariable(&r_lerpsprites);
4227 Cvar_RegisterVariable(&r_lerpmodels);
4228 Cvar_RegisterVariable(&r_lerplightstyles);
4229 Cvar_RegisterVariable(&r_waterscroll);
4230 Cvar_RegisterVariable(&r_bloom);
4231 Cvar_RegisterVariable(&r_bloom_colorscale);
4232 Cvar_RegisterVariable(&r_bloom_brighten);
4233 Cvar_RegisterVariable(&r_bloom_blur);
4234 Cvar_RegisterVariable(&r_bloom_resolution);
4235 Cvar_RegisterVariable(&r_bloom_colorexponent);
4236 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4237 Cvar_RegisterVariable(&r_hdr);
4238 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4239 Cvar_RegisterVariable(&r_hdr_glowintensity);
4240 Cvar_RegisterVariable(&r_hdr_range);
4241 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4242 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4243 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4244 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4245 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4246 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4247 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4248 Cvar_RegisterVariable(&developer_texturelogging);
4249 Cvar_RegisterVariable(&gl_lightmaps);
4250 Cvar_RegisterVariable(&r_test);
4251 Cvar_RegisterVariable(&r_glsl_saturation);
4252 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4253 Cvar_RegisterVariable(&r_framedatasize);
4254 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4255 Cvar_SetValue("r_fullbrights", 0);
4256 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4258 Cvar_RegisterVariable(&r_track_sprites);
4259 Cvar_RegisterVariable(&r_track_sprites_flags);
4260 Cvar_RegisterVariable(&r_track_sprites_scalew);
4261 Cvar_RegisterVariable(&r_track_sprites_scaleh);
4262 Cvar_RegisterVariable(&r_overheadsprites_perspective);
4263 Cvar_RegisterVariable(&r_overheadsprites_pushback);
4264 Cvar_RegisterVariable(&r_overheadsprites_scalex);
4265 Cvar_RegisterVariable(&r_overheadsprites_scaley);
4268 extern void R_Textures_Init(void);
4269 extern void GL_Draw_Init(void);
4270 extern void GL_Main_Init(void);
4271 extern void R_Shadow_Init(void);
4272 extern void R_Sky_Init(void);
4273 extern void GL_Surf_Init(void);
4274 extern void R_Particles_Init(void);
4275 extern void R_Explosion_Init(void);
4276 extern void gl_backend_init(void);
4277 extern void Sbar_Init(void);
4278 extern void R_LightningBeams_Init(void);
4279 extern void Mod_RenderInit(void);
4280 extern void Font_Init(void);
4282 void Render_Init(void)
4295 R_LightningBeams_Init();
4304 extern char *ENGINE_EXTENSIONS;
4307 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4308 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4309 gl_version = (const char *)qglGetString(GL_VERSION);
4310 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4314 if (!gl_platformextensions)
4315 gl_platformextensions = "";
4317 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4318 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4319 Con_Printf("GL_VERSION: %s\n", gl_version);
4320 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4321 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4323 VID_CheckExtensions();
4325 // LordHavoc: report supported extensions
4326 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4328 // clear to black (loading plaque will be seen over this)
4329 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4332 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4336 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4338 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4341 p = r_refdef.view.frustum + i;
4346 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4350 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4354 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4358 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4362 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4366 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4370 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4374 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4382 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4386 for (i = 0;i < numplanes;i++)
4393 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4397 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4401 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4405 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4409 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4413 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4417 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4421 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4429 //==================================================================================
4431 // LordHavoc: this stores temporary data used within the same frame
4433 typedef struct r_framedata_mem_s
4435 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4436 size_t size; // how much usable space
4437 size_t current; // how much space in use
4438 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4439 size_t wantedsize; // how much space was allocated
4440 unsigned char *data; // start of real data (16byte aligned)
4444 static r_framedata_mem_t *r_framedata_mem;
4446 void R_FrameData_Reset(void)
4448 while (r_framedata_mem)
4450 r_framedata_mem_t *next = r_framedata_mem->purge;
4451 Mem_Free(r_framedata_mem);
4452 r_framedata_mem = next;
4456 void R_FrameData_Resize(void)
4459 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4460 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4461 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4463 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4464 newmem->wantedsize = wantedsize;
4465 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4466 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4467 newmem->current = 0;
4469 newmem->purge = r_framedata_mem;
4470 r_framedata_mem = newmem;
4474 void R_FrameData_NewFrame(void)
4476 R_FrameData_Resize();
4477 if (!r_framedata_mem)
4479 // if we ran out of space on the last frame, free the old memory now
4480 while (r_framedata_mem->purge)
4482 // repeatedly remove the second item in the list, leaving only head
4483 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4484 Mem_Free(r_framedata_mem->purge);
4485 r_framedata_mem->purge = next;
4487 // reset the current mem pointer
4488 r_framedata_mem->current = 0;
4489 r_framedata_mem->mark = 0;
4492 void *R_FrameData_Alloc(size_t size)
4496 // align to 16 byte boundary - the data pointer is already aligned, so we
4497 // only need to ensure the size of every allocation is also aligned
4498 size = (size + 15) & ~15;
4500 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4502 // emergency - we ran out of space, allocate more memory
4503 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4504 R_FrameData_Resize();
4507 data = r_framedata_mem->data + r_framedata_mem->current;
4508 r_framedata_mem->current += size;
4510 // count the usage for stats
4511 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4512 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4514 return (void *)data;
4517 void *R_FrameData_Store(size_t size, void *data)
4519 void *d = R_FrameData_Alloc(size);
4521 memcpy(d, data, size);
4525 void R_FrameData_SetMark(void)
4527 if (!r_framedata_mem)
4529 r_framedata_mem->mark = r_framedata_mem->current;
4532 void R_FrameData_ReturnToMark(void)
4534 if (!r_framedata_mem)
4536 r_framedata_mem->current = r_framedata_mem->mark;
4539 //==================================================================================
4541 // LordHavoc: animcache originally written by Echon, rewritten since then
4544 * Animation cache prevents re-generating mesh data for an animated model
4545 * multiple times in one frame for lighting, shadowing, reflections, etc.
4548 void R_AnimCache_Free(void)
4552 void R_AnimCache_ClearCache(void)
4555 entity_render_t *ent;
4557 for (i = 0;i < r_refdef.scene.numentities;i++)
4559 ent = r_refdef.scene.entities[i];
4560 ent->animcache_vertex3f = NULL;
4561 ent->animcache_normal3f = NULL;
4562 ent->animcache_svector3f = NULL;
4563 ent->animcache_tvector3f = NULL;
4564 ent->animcache_vertexmesh = NULL;
4565 ent->animcache_vertex3fbuffer = NULL;
4566 ent->animcache_vertexmeshbuffer = NULL;
4570 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4574 // check if we need the meshbuffers
4575 if (!vid.useinterleavedarrays)
4578 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4579 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4580 // TODO: upload vertex3f buffer?
4581 if (ent->animcache_vertexmesh)
4583 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4584 for (i = 0;i < numvertices;i++)
4585 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4586 if (ent->animcache_svector3f)
4587 for (i = 0;i < numvertices;i++)
4588 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4589 if (ent->animcache_tvector3f)
4590 for (i = 0;i < numvertices;i++)
4591 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4592 if (ent->animcache_normal3f)
4593 for (i = 0;i < numvertices;i++)
4594 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4595 // TODO: upload vertexmeshbuffer?
4599 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4601 dp_model_t *model = ent->model;
4603 // see if it's already cached this frame
4604 if (ent->animcache_vertex3f)
4606 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4607 if (wantnormals || wanttangents)
4609 if (ent->animcache_normal3f)
4610 wantnormals = false;
4611 if (ent->animcache_svector3f)
4612 wanttangents = false;
4613 if (wantnormals || wanttangents)
4615 numvertices = model->surfmesh.num_vertices;
4617 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4620 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4621 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4623 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4624 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4630 // see if this ent is worth caching
4631 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4633 // get some memory for this entity and generate mesh data
4634 numvertices = model->surfmesh.num_vertices;
4635 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4637 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4640 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4641 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4643 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4644 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4649 void R_AnimCache_CacheVisibleEntities(void)
4652 qboolean wantnormals = true;
4653 qboolean wanttangents = !r_showsurfaces.integer;
4655 switch(vid.renderpath)
4657 case RENDERPATH_GL20:
4658 case RENDERPATH_D3D9:
4659 case RENDERPATH_D3D10:
4660 case RENDERPATH_D3D11:
4661 case RENDERPATH_GLES2:
4663 case RENDERPATH_GL13:
4664 case RENDERPATH_GL11:
4665 wanttangents = false;
4667 case RENDERPATH_SOFT:
4671 if (r_shownormals.integer)
4672 wanttangents = wantnormals = true;
4674 // TODO: thread this
4675 // NOTE: R_PrepareRTLights() also caches entities
4677 for (i = 0;i < r_refdef.scene.numentities;i++)
4678 if (r_refdef.viewcache.entityvisible[i])
4679 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4682 //==================================================================================
4684 static void R_View_UpdateEntityLighting (void)
4687 entity_render_t *ent;
4688 vec3_t tempdiffusenormal, avg;
4689 vec_t f, fa, fd, fdd;
4690 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4692 for (i = 0;i < r_refdef.scene.numentities;i++)
4694 ent = r_refdef.scene.entities[i];
4696 // skip unseen models
4697 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4701 if (ent->model && ent->model->brush.num_leafs)
4703 // TODO: use modellight for r_ambient settings on world?
4704 VectorSet(ent->modellight_ambient, 0, 0, 0);
4705 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4706 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4710 // fetch the lighting from the worldmodel data
4711 VectorClear(ent->modellight_ambient);
4712 VectorClear(ent->modellight_diffuse);
4713 VectorClear(tempdiffusenormal);
4714 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4717 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4719 // complete lightning for lit sprites
4720 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4721 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4723 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4724 org[2] = org[2] + r_overheadsprites_pushback.value;
4725 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4728 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4730 if(ent->flags & RENDER_EQUALIZE)
4732 // first fix up ambient lighting...
4733 if(r_equalize_entities_minambient.value > 0)
4735 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4738 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4739 if(fa < r_equalize_entities_minambient.value * fd)
4742 // fa'/fd' = minambient
4743 // fa'+0.25*fd' = fa+0.25*fd
4745 // fa' = fd' * minambient
4746 // fd'*(0.25+minambient) = fa+0.25*fd
4748 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4749 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4751 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4752 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
4753 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4754 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4759 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4761 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4762 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4766 // adjust brightness and saturation to target
4767 avg[0] = avg[1] = avg[2] = fa / f;
4768 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4769 avg[0] = avg[1] = avg[2] = fd / f;
4770 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4776 VectorSet(ent->modellight_ambient, 1, 1, 1);
4778 // move the light direction into modelspace coordinates for lighting code
4779 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4780 if(VectorLength2(ent->modellight_lightdir) == 0)
4781 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4782 VectorNormalize(ent->modellight_lightdir);
4786 #define MAX_LINEOFSIGHTTRACES 64
4788 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4791 vec3_t boxmins, boxmaxs;
4794 dp_model_t *model = r_refdef.scene.worldmodel;
4796 if (!model || !model->brush.TraceLineOfSight)
4799 // expand the box a little
4800 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4801 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4802 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4803 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4804 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4805 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4807 // return true if eye is inside enlarged box
4808 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4812 VectorCopy(eye, start);
4813 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4814 if (model->brush.TraceLineOfSight(model, start, end))
4817 // try various random positions
4818 for (i = 0;i < numsamples;i++)
4820 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4821 if (model->brush.TraceLineOfSight(model, start, end))
4829 static void R_View_UpdateEntityVisible (void)
4834 entity_render_t *ent;
4836 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4837 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4838 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
4839 : RENDER_EXTERIORMODEL;
4840 if (!r_drawviewmodel.integer)
4841 renderimask |= RENDER_VIEWMODEL;
4842 if (!r_drawexteriormodel.integer)
4843 renderimask |= RENDER_EXTERIORMODEL;
4844 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4846 // worldmodel can check visibility
4847 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4848 for (i = 0;i < r_refdef.scene.numentities;i++)
4850 ent = r_refdef.scene.entities[i];
4851 if (!(ent->flags & renderimask))
4852 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)))
4853 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))
4854 r_refdef.viewcache.entityvisible[i] = true;
4856 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4857 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4859 for (i = 0;i < r_refdef.scene.numentities;i++)
4861 ent = r_refdef.scene.entities[i];
4862 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4864 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4866 continue; // temp entities do pvs only
4867 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4868 ent->last_trace_visibility = realtime;
4869 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4870 r_refdef.viewcache.entityvisible[i] = 0;
4877 // no worldmodel or it can't check visibility
4878 for (i = 0;i < r_refdef.scene.numentities;i++)
4880 ent = r_refdef.scene.entities[i];
4881 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));
4886 /// only used if skyrendermasked, and normally returns false
4887 int R_DrawBrushModelsSky (void)
4890 entity_render_t *ent;
4893 for (i = 0;i < r_refdef.scene.numentities;i++)
4895 if (!r_refdef.viewcache.entityvisible[i])
4897 ent = r_refdef.scene.entities[i];
4898 if (!ent->model || !ent->model->DrawSky)
4900 ent->model->DrawSky(ent);
4906 static void R_DrawNoModel(entity_render_t *ent);
4907 static void R_DrawModels(void)
4910 entity_render_t *ent;
4912 for (i = 0;i < r_refdef.scene.numentities;i++)
4914 if (!r_refdef.viewcache.entityvisible[i])
4916 ent = r_refdef.scene.entities[i];
4917 r_refdef.stats.entities++;
4918 if (ent->model && ent->model->Draw != NULL)
4919 ent->model->Draw(ent);
4925 static void R_DrawModelsDepth(void)
4928 entity_render_t *ent;
4930 for (i = 0;i < r_refdef.scene.numentities;i++)
4932 if (!r_refdef.viewcache.entityvisible[i])
4934 ent = r_refdef.scene.entities[i];
4935 if (ent->model && ent->model->DrawDepth != NULL)
4936 ent->model->DrawDepth(ent);
4940 static void R_DrawModelsDebug(void)
4943 entity_render_t *ent;
4945 for (i = 0;i < r_refdef.scene.numentities;i++)
4947 if (!r_refdef.viewcache.entityvisible[i])
4949 ent = r_refdef.scene.entities[i];
4950 if (ent->model && ent->model->DrawDebug != NULL)
4951 ent->model->DrawDebug(ent);
4955 static void R_DrawModelsAddWaterPlanes(void)
4958 entity_render_t *ent;
4960 for (i = 0;i < r_refdef.scene.numentities;i++)
4962 if (!r_refdef.viewcache.entityvisible[i])
4964 ent = r_refdef.scene.entities[i];
4965 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4966 ent->model->DrawAddWaterPlanes(ent);
4970 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4972 if (r_hdr_irisadaptation.integer)
4976 vec3_t diffusenormal;
4981 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4982 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4983 brightness = max(0.0000001f, brightness);
4984 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4985 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4986 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4987 current = r_hdr_irisadaptation_value.value;
4989 current = min(current + adjust, goal);
4990 else if (current > goal)
4991 current = max(current - adjust, goal);
4992 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4993 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4995 else if (r_hdr_irisadaptation_value.value != 1.0f)
4996 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4999 static void R_View_SetFrustum(const int *scissor)
5002 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5003 vec3_t forward, left, up, origin, v;
5007 // flipped x coordinates (because x points left here)
5008 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5009 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5011 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5012 switch(vid.renderpath)
5014 case RENDERPATH_D3D9:
5015 case RENDERPATH_D3D10:
5016 case RENDERPATH_D3D11:
5017 case RENDERPATH_SOFT:
5018 // non-flipped y coordinates
5019 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5020 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5022 case RENDERPATH_GL11:
5023 case RENDERPATH_GL13:
5024 case RENDERPATH_GL20:
5025 case RENDERPATH_GLES2:
5026 // non-flipped y coordinates
5027 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5028 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5033 // we can't trust r_refdef.view.forward and friends in reflected scenes
5034 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5037 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5038 r_refdef.view.frustum[0].normal[1] = 0 - 0;
5039 r_refdef.view.frustum[0].normal[2] = -1 - 0;
5040 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5041 r_refdef.view.frustum[1].normal[1] = 0 + 0;
5042 r_refdef.view.frustum[1].normal[2] = -1 + 0;
5043 r_refdef.view.frustum[2].normal[0] = 0 - 0;
5044 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5045 r_refdef.view.frustum[2].normal[2] = -1 - 0;
5046 r_refdef.view.frustum[3].normal[0] = 0 + 0;
5047 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5048 r_refdef.view.frustum[3].normal[2] = -1 + 0;
5052 zNear = r_refdef.nearclip;
5053 nudge = 1.0 - 1.0 / (1<<23);
5054 r_refdef.view.frustum[4].normal[0] = 0 - 0;
5055 r_refdef.view.frustum[4].normal[1] = 0 - 0;
5056 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5057 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5058 r_refdef.view.frustum[5].normal[0] = 0 + 0;
5059 r_refdef.view.frustum[5].normal[1] = 0 + 0;
5060 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5061 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5067 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5068 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5069 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5070 r_refdef.view.frustum[0].dist = m[15] - m[12];
5072 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5073 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5074 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5075 r_refdef.view.frustum[1].dist = m[15] + m[12];
5077 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5078 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5079 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5080 r_refdef.view.frustum[2].dist = m[15] - m[13];
5082 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5083 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5084 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5085 r_refdef.view.frustum[3].dist = m[15] + m[13];
5087 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5088 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5089 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5090 r_refdef.view.frustum[4].dist = m[15] - m[14];
5092 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5093 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5094 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5095 r_refdef.view.frustum[5].dist = m[15] + m[14];
5098 if (r_refdef.view.useperspective)
5100 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5101 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]);
5102 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]);
5103 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]);
5104 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]);
5106 // then the normals from the corners relative to origin
5107 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5108 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5109 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5110 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5112 // in a NORMAL view, forward cross left == up
5113 // in a REFLECTED view, forward cross left == down
5114 // so our cross products above need to be adjusted for a left handed coordinate system
5115 CrossProduct(forward, left, v);
5116 if(DotProduct(v, up) < 0)
5118 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5119 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5120 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5121 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5124 // Leaving those out was a mistake, those were in the old code, and they
5125 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5126 // I couldn't reproduce it after adding those normalizations. --blub
5127 VectorNormalize(r_refdef.view.frustum[0].normal);
5128 VectorNormalize(r_refdef.view.frustum[1].normal);
5129 VectorNormalize(r_refdef.view.frustum[2].normal);
5130 VectorNormalize(r_refdef.view.frustum[3].normal);
5132 // make the corners absolute
5133 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5134 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5135 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5136 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5139 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5141 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5142 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5143 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5144 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5145 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5149 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5150 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5151 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5152 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5153 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5154 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5155 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5156 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5157 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5158 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5160 r_refdef.view.numfrustumplanes = 5;
5162 if (r_refdef.view.useclipplane)
5164 r_refdef.view.numfrustumplanes = 6;
5165 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5168 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5169 PlaneClassify(r_refdef.view.frustum + i);
5171 // LordHavoc: note to all quake engine coders, Quake had a special case
5172 // for 90 degrees which assumed a square view (wrong), so I removed it,
5173 // Quake2 has it disabled as well.
5175 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5176 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5177 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5178 //PlaneClassify(&frustum[0]);
5180 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5181 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5182 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5183 //PlaneClassify(&frustum[1]);
5185 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5186 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5187 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5188 //PlaneClassify(&frustum[2]);
5190 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5191 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5192 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5193 //PlaneClassify(&frustum[3]);
5196 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5197 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5198 //PlaneClassify(&frustum[4]);
5201 void R_View_UpdateWithScissor(const int *myscissor)
5203 R_Main_ResizeViewCache();
5204 R_View_SetFrustum(myscissor);
5205 R_View_WorldVisibility(r_refdef.view.useclipplane);
5206 R_View_UpdateEntityVisible();
5207 R_View_UpdateEntityLighting();
5210 void R_View_Update(void)
5212 R_Main_ResizeViewCache();
5213 R_View_SetFrustum(NULL);
5214 R_View_WorldVisibility(r_refdef.view.useclipplane);
5215 R_View_UpdateEntityVisible();
5216 R_View_UpdateEntityLighting();
5219 void R_SetupView(qboolean allowwaterclippingplane)
5221 const float *customclipplane = NULL;
5223 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5225 // LordHavoc: couldn't figure out how to make this approach the
5226 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5227 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5228 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5229 dist = r_refdef.view.clipplane.dist;
5230 plane[0] = r_refdef.view.clipplane.normal[0];
5231 plane[1] = r_refdef.view.clipplane.normal[1];
5232 plane[2] = r_refdef.view.clipplane.normal[2];
5234 customclipplane = plane;
5237 if (!r_refdef.view.useperspective)
5238 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);
5239 else if (vid.stencil && r_useinfinitefarclip.integer)
5240 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);
5242 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);
5243 R_SetViewport(&r_refdef.view.viewport);
5246 void R_EntityMatrix(const matrix4x4_t *matrix)
5248 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5250 gl_modelmatrixchanged = false;
5251 gl_modelmatrix = *matrix;
5252 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5253 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5254 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5255 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5257 switch(vid.renderpath)
5259 case RENDERPATH_D3D9:
5261 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5262 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5265 case RENDERPATH_D3D10:
5266 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5268 case RENDERPATH_D3D11:
5269 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5271 case RENDERPATH_GL13:
5272 case RENDERPATH_GL11:
5273 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5275 case RENDERPATH_SOFT:
5276 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5277 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5279 case RENDERPATH_GL20:
5280 case RENDERPATH_GLES2:
5281 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5282 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5288 void R_ResetViewRendering2D(void)
5290 r_viewport_t viewport;
5293 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5294 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);
5295 R_SetViewport(&viewport);
5296 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5297 GL_Color(1, 1, 1, 1);
5298 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5299 GL_BlendFunc(GL_ONE, GL_ZERO);
5300 GL_ScissorTest(false);
5301 GL_DepthMask(false);
5302 GL_DepthRange(0, 1);
5303 GL_DepthTest(false);
5304 GL_DepthFunc(GL_LEQUAL);
5305 R_EntityMatrix(&identitymatrix);
5306 R_Mesh_ResetTextureState();
5307 GL_PolygonOffset(0, 0);
5308 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5309 switch(vid.renderpath)
5311 case RENDERPATH_GL11:
5312 case RENDERPATH_GL13:
5313 case RENDERPATH_GL20:
5314 case RENDERPATH_GLES2:
5315 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5317 case RENDERPATH_D3D9:
5318 case RENDERPATH_D3D10:
5319 case RENDERPATH_D3D11:
5320 case RENDERPATH_SOFT:
5323 GL_CullFace(GL_NONE);
5326 void R_ResetViewRendering3D(void)
5331 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5332 GL_Color(1, 1, 1, 1);
5333 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5334 GL_BlendFunc(GL_ONE, GL_ZERO);
5335 GL_ScissorTest(true);
5337 GL_DepthRange(0, 1);
5339 GL_DepthFunc(GL_LEQUAL);
5340 R_EntityMatrix(&identitymatrix);
5341 R_Mesh_ResetTextureState();
5342 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5343 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5344 switch(vid.renderpath)
5346 case RENDERPATH_GL11:
5347 case RENDERPATH_GL13:
5348 case RENDERPATH_GL20:
5349 case RENDERPATH_GLES2:
5350 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5352 case RENDERPATH_D3D9:
5353 case RENDERPATH_D3D10:
5354 case RENDERPATH_D3D11:
5355 case RENDERPATH_SOFT:
5358 GL_CullFace(r_refdef.view.cullface_back);
5363 R_RenderView_UpdateViewVectors
5366 static void R_RenderView_UpdateViewVectors(void)
5368 // break apart the view matrix into vectors for various purposes
5369 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5370 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5371 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5372 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5373 // make an inverted copy of the view matrix for tracking sprites
5374 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5377 void R_RenderScene(void);
5378 void R_RenderWaterPlanes(void);
5380 static void R_Water_StartFrame(void)
5383 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5384 r_waterstate_waterplane_t *p;
5386 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5389 switch(vid.renderpath)
5391 case RENDERPATH_GL20:
5392 case RENDERPATH_D3D9:
5393 case RENDERPATH_D3D10:
5394 case RENDERPATH_D3D11:
5395 case RENDERPATH_SOFT:
5396 case RENDERPATH_GLES2:
5398 case RENDERPATH_GL13:
5399 case RENDERPATH_GL11:
5403 // set waterwidth and waterheight to the water resolution that will be
5404 // used (often less than the screen resolution for faster rendering)
5405 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5406 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5408 // calculate desired texture sizes
5409 // can't use water if the card does not support the texture size
5410 if (!r_water.integer || r_showsurfaces.integer)
5411 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5412 else if (vid.support.arb_texture_non_power_of_two)
5414 texturewidth = waterwidth;
5415 textureheight = waterheight;
5416 camerawidth = waterwidth;
5417 cameraheight = waterheight;
5421 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5422 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5423 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5424 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5427 // allocate textures as needed
5428 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5430 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5431 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5433 if (p->texture_refraction)
5434 R_FreeTexture(p->texture_refraction);
5435 p->texture_refraction = NULL;
5436 if (p->texture_reflection)
5437 R_FreeTexture(p->texture_reflection);
5438 p->texture_reflection = NULL;
5439 if (p->texture_camera)
5440 R_FreeTexture(p->texture_camera);
5441 p->texture_camera = NULL;
5443 memset(&r_waterstate, 0, sizeof(r_waterstate));
5444 r_waterstate.texturewidth = texturewidth;
5445 r_waterstate.textureheight = textureheight;
5446 r_waterstate.camerawidth = camerawidth;
5447 r_waterstate.cameraheight = cameraheight;
5450 if (r_waterstate.texturewidth)
5452 r_waterstate.enabled = true;
5454 // when doing a reduced render (HDR) we want to use a smaller area
5455 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5456 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5458 // set up variables that will be used in shader setup
5459 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5460 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5461 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5462 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5465 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5466 r_waterstate.numwaterplanes = 0;
5469 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5471 int triangleindex, planeindex;
5477 r_waterstate_waterplane_t *p;
5478 texture_t *t = R_GetCurrentTexture(surface->texture);
5480 // just use the first triangle with a valid normal for any decisions
5481 VectorClear(normal);
5482 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5484 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5485 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5486 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5487 TriangleNormal(vert[0], vert[1], vert[2], normal);
5488 if (VectorLength2(normal) >= 0.001)
5492 VectorCopy(normal, plane.normal);
5493 VectorNormalize(plane.normal);
5494 plane.dist = DotProduct(vert[0], plane.normal);
5495 PlaneClassify(&plane);
5496 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5498 // skip backfaces (except if nocullface is set)
5499 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5501 VectorNegate(plane.normal, plane.normal);
5503 PlaneClassify(&plane);
5507 // find a matching plane if there is one
5508 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5509 if(p->camera_entity == t->camera_entity)
5510 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5512 if (planeindex >= r_waterstate.maxwaterplanes)
5513 return; // nothing we can do, out of planes
5515 // if this triangle does not fit any known plane rendered this frame, add one
5516 if (planeindex >= r_waterstate.numwaterplanes)
5518 // store the new plane
5519 r_waterstate.numwaterplanes++;
5521 // clear materialflags and pvs
5522 p->materialflags = 0;
5523 p->pvsvalid = false;
5524 p->camera_entity = t->camera_entity;
5525 VectorCopy(surface->mins, p->mins);
5526 VectorCopy(surface->maxs, p->maxs);
5531 p->mins[0] = min(p->mins[0], surface->mins[0]);
5532 p->mins[1] = min(p->mins[1], surface->mins[1]);
5533 p->mins[2] = min(p->mins[2], surface->mins[2]);
5534 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5535 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5536 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5538 // merge this surface's materialflags into the waterplane
5539 p->materialflags |= t->currentmaterialflags;
5540 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5542 // merge this surface's PVS into the waterplane
5543 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5544 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5545 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5547 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5553 static void R_Water_ProcessPlanes(void)
5556 r_refdef_view_t originalview;
5557 r_refdef_view_t myview;
5559 r_waterstate_waterplane_t *p;
5562 originalview = r_refdef.view;
5564 // make sure enough textures are allocated
5565 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5567 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5569 if (!p->texture_refraction)
5570 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);
5571 if (!p->texture_refraction)
5574 else if (p->materialflags & MATERIALFLAG_CAMERA)
5576 if (!p->texture_camera)
5577 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);
5578 if (!p->texture_camera)
5582 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5584 if (!p->texture_reflection)
5585 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);
5586 if (!p->texture_reflection)
5592 r_refdef.view = originalview;
5593 r_refdef.view.showdebug = false;
5594 r_refdef.view.width = r_waterstate.waterwidth;
5595 r_refdef.view.height = r_waterstate.waterheight;
5596 r_refdef.view.useclipplane = true;
5597 myview = r_refdef.view;
5598 r_waterstate.renderingscene = true;
5599 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5601 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5603 r_refdef.view = myview;
5604 if(r_water_scissormode.integer)
5607 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5608 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5611 // render reflected scene and copy into texture
5612 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5613 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5614 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5615 r_refdef.view.clipplane = p->plane;
5617 // reverse the cullface settings for this render
5618 r_refdef.view.cullface_front = GL_FRONT;
5619 r_refdef.view.cullface_back = GL_BACK;
5620 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5622 r_refdef.view.usecustompvs = true;
5624 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5626 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5629 R_ResetViewRendering3D();
5630 R_ClearScreen(r_refdef.fogenabled);
5631 if(r_water_scissormode.integer & 2)
5632 R_View_UpdateWithScissor(myscissor);
5635 if(r_water_scissormode.integer & 1)
5636 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5639 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);
5642 // render the normal view scene and copy into texture
5643 // (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)
5644 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5646 r_refdef.view = myview;
5647 if(r_water_scissormode.integer)
5650 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5651 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5654 r_waterstate.renderingrefraction = true;
5656 r_refdef.view.clipplane = p->plane;
5657 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5658 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5660 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5662 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5663 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5664 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5665 R_RenderView_UpdateViewVectors();
5666 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5668 r_refdef.view.usecustompvs = true;
5669 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);
5673 PlaneClassify(&r_refdef.view.clipplane);
5675 R_ResetViewRendering3D();
5676 R_ClearScreen(r_refdef.fogenabled);
5677 if(r_water_scissormode.integer & 2)
5678 R_View_UpdateWithScissor(myscissor);
5681 if(r_water_scissormode.integer & 1)
5682 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5685 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);
5686 r_waterstate.renderingrefraction = false;
5688 else if (p->materialflags & MATERIALFLAG_CAMERA)
5690 r_refdef.view = myview;
5692 r_refdef.view.clipplane = p->plane;
5693 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5694 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5696 r_refdef.view.width = r_waterstate.camerawidth;
5697 r_refdef.view.height = r_waterstate.cameraheight;
5698 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5699 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5701 if(p->camera_entity)
5703 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5704 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5707 // note: all of the view is used for displaying... so
5708 // there is no use in scissoring
5710 // reverse the cullface settings for this render
5711 r_refdef.view.cullface_front = GL_FRONT;
5712 r_refdef.view.cullface_back = GL_BACK;
5713 // also reverse the view matrix
5714 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
5715 R_RenderView_UpdateViewVectors();
5716 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5718 r_refdef.view.usecustompvs = true;
5719 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);
5722 // camera needs no clipplane
5723 r_refdef.view.useclipplane = false;
5725 PlaneClassify(&r_refdef.view.clipplane);
5727 R_ResetViewRendering3D();
5728 R_ClearScreen(r_refdef.fogenabled);
5732 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);
5733 r_waterstate.renderingrefraction = false;
5737 r_waterstate.renderingscene = false;
5738 r_refdef.view = originalview;
5739 R_ResetViewRendering3D();
5740 R_ClearScreen(r_refdef.fogenabled);
5744 r_refdef.view = originalview;
5745 r_waterstate.renderingscene = false;
5746 Cvar_SetValueQuick(&r_water, 0);
5747 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5751 void R_Bloom_StartFrame(void)
5753 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5755 switch(vid.renderpath)
5757 case RENDERPATH_GL20:
5758 case RENDERPATH_D3D9:
5759 case RENDERPATH_D3D10:
5760 case RENDERPATH_D3D11:
5761 case RENDERPATH_SOFT:
5762 case RENDERPATH_GLES2:
5764 case RENDERPATH_GL13:
5765 case RENDERPATH_GL11:
5769 // set bloomwidth and bloomheight to the bloom resolution that will be
5770 // used (often less than the screen resolution for faster rendering)
5771 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5772 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5773 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5774 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5775 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5777 // calculate desired texture sizes
5778 if (vid.support.arb_texture_non_power_of_two)
5780 screentexturewidth = r_refdef.view.width;
5781 screentextureheight = r_refdef.view.height;
5782 bloomtexturewidth = r_bloomstate.bloomwidth;
5783 bloomtextureheight = r_bloomstate.bloomheight;
5787 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
5788 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
5789 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
5790 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
5793 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))
5795 Cvar_SetValueQuick(&r_hdr, 0);
5796 Cvar_SetValueQuick(&r_bloom, 0);
5797 Cvar_SetValueQuick(&r_motionblur, 0);
5798 Cvar_SetValueQuick(&r_damageblur, 0);
5801 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)))
5802 screentexturewidth = screentextureheight = 0;
5803 if (!r_hdr.integer && !r_bloom.integer)
5804 bloomtexturewidth = bloomtextureheight = 0;
5806 // allocate textures as needed
5807 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
5809 if (r_bloomstate.texture_screen)
5810 R_FreeTexture(r_bloomstate.texture_screen);
5811 r_bloomstate.texture_screen = NULL;
5812 r_bloomstate.screentexturewidth = screentexturewidth;
5813 r_bloomstate.screentextureheight = screentextureheight;
5814 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5815 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);
5817 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
5819 if (r_bloomstate.texture_bloom)
5820 R_FreeTexture(r_bloomstate.texture_bloom);
5821 r_bloomstate.texture_bloom = NULL;
5822 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5823 r_bloomstate.bloomtextureheight = bloomtextureheight;
5824 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5825 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);
5828 // when doing a reduced render (HDR) we want to use a smaller area
5829 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5830 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5831 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5832 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5833 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5835 // set up a texcoord array for the full resolution screen image
5836 // (we have to keep this around to copy back during final render)
5837 r_bloomstate.screentexcoord2f[0] = 0;
5838 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
5839 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
5840 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
5841 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
5842 r_bloomstate.screentexcoord2f[5] = 0;
5843 r_bloomstate.screentexcoord2f[6] = 0;
5844 r_bloomstate.screentexcoord2f[7] = 0;
5846 // set up a texcoord array for the reduced resolution bloom image
5847 // (which will be additive blended over the screen image)
5848 r_bloomstate.bloomtexcoord2f[0] = 0;
5849 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5850 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5851 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5852 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5853 r_bloomstate.bloomtexcoord2f[5] = 0;
5854 r_bloomstate.bloomtexcoord2f[6] = 0;
5855 r_bloomstate.bloomtexcoord2f[7] = 0;
5857 switch(vid.renderpath)
5859 case RENDERPATH_GL11:
5860 case RENDERPATH_GL13:
5861 case RENDERPATH_GL20:
5862 case RENDERPATH_SOFT:
5863 case RENDERPATH_GLES2:
5865 case RENDERPATH_D3D9:
5866 case RENDERPATH_D3D10:
5867 case RENDERPATH_D3D11:
5870 for (i = 0;i < 4;i++)
5872 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5873 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5874 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5875 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5881 if (r_hdr.integer || r_bloom.integer)
5883 r_bloomstate.enabled = true;
5884 r_bloomstate.hdr = r_hdr.integer != 0;
5887 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);
5890 void R_Bloom_CopyBloomTexture(float colorscale)
5892 r_refdef.stats.bloom++;
5894 // scale down screen texture to the bloom texture size
5896 R_SetViewport(&r_bloomstate.viewport);
5897 GL_BlendFunc(GL_ONE, GL_ZERO);
5898 GL_Color(colorscale, colorscale, colorscale, 1);
5899 // 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...
5900 switch(vid.renderpath)
5902 case RENDERPATH_GL11:
5903 case RENDERPATH_GL13:
5904 case RENDERPATH_GL20:
5905 case RENDERPATH_SOFT:
5906 case RENDERPATH_GLES2:
5907 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5909 case RENDERPATH_D3D9:
5910 case RENDERPATH_D3D10:
5911 case RENDERPATH_D3D11:
5912 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5915 // TODO: do boxfilter scale-down in shader?
5916 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5917 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5918 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5920 // we now have a bloom image in the framebuffer
5921 // copy it into the bloom image texture for later processing
5922 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);
5923 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5926 void R_Bloom_CopyHDRTexture(void)
5928 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);
5929 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5932 void R_Bloom_MakeTexture(void)
5935 float xoffset, yoffset, r, brighten;
5937 r_refdef.stats.bloom++;
5939 R_ResetViewRendering2D();
5941 // we have a bloom image in the framebuffer
5943 R_SetViewport(&r_bloomstate.viewport);
5945 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5948 r = bound(0, r_bloom_colorexponent.value / x, 1);
5949 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5951 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5952 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5953 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5954 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5956 // copy the vertically blurred bloom view to a texture
5957 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);
5958 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5961 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5962 brighten = r_bloom_brighten.value;
5964 brighten *= r_hdr_range.value;
5965 brighten = sqrt(brighten);
5967 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5968 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5970 for (dir = 0;dir < 2;dir++)
5972 // blend on at multiple vertical offsets to achieve a vertical blur
5973 // TODO: do offset blends using GLSL
5974 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5975 GL_BlendFunc(GL_ONE, GL_ZERO);
5976 for (x = -range;x <= range;x++)
5978 if (!dir){xoffset = 0;yoffset = x;}
5979 else {xoffset = x;yoffset = 0;}
5980 xoffset /= (float)r_bloomstate.bloomtexturewidth;
5981 yoffset /= (float)r_bloomstate.bloomtextureheight;
5982 // compute a texcoord array with the specified x and y offset
5983 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
5984 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5985 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5986 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5987 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5988 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
5989 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
5990 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
5991 // this r value looks like a 'dot' particle, fading sharply to
5992 // black at the edges
5993 // (probably not realistic but looks good enough)
5994 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
5995 //r = brighten/(range*2+1);
5996 r = brighten / (range * 2 + 1);
5998 r *= (1 - x*x/(float)(range*range));
5999 GL_Color(r, r, r, 1);
6000 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6001 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6002 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6003 GL_BlendFunc(GL_ONE, GL_ONE);
6006 // copy the vertically blurred bloom view to a texture
6007 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);
6008 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6012 void R_HDR_RenderBloomTexture(void)
6014 int oldwidth, oldheight;
6015 float oldcolorscale;
6016 qboolean oldwaterstate;
6018 oldwaterstate = r_waterstate.enabled;
6019 oldcolorscale = r_refdef.view.colorscale;
6020 oldwidth = r_refdef.view.width;
6021 oldheight = r_refdef.view.height;
6022 r_refdef.view.width = r_bloomstate.bloomwidth;
6023 r_refdef.view.height = r_bloomstate.bloomheight;
6025 if(r_hdr.integer < 2)
6026 r_waterstate.enabled = false;
6028 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
6029 // TODO: add exposure compensation features
6030 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6032 r_refdef.view.showdebug = false;
6033 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6035 R_ResetViewRendering3D();
6037 R_ClearScreen(r_refdef.fogenabled);
6038 if (r_timereport_active)
6039 R_TimeReport("HDRclear");
6042 if (r_timereport_active)
6043 R_TimeReport("visibility");
6045 // only do secondary renders with HDR if r_hdr is 2 or higher
6046 r_waterstate.numwaterplanes = 0;
6047 if (r_waterstate.enabled)
6048 R_RenderWaterPlanes();
6050 r_refdef.view.showdebug = true;
6052 r_waterstate.numwaterplanes = 0;
6054 R_ResetViewRendering2D();
6056 R_Bloom_CopyHDRTexture();
6057 R_Bloom_MakeTexture();
6059 // restore the view settings
6060 r_waterstate.enabled = oldwaterstate;
6061 r_refdef.view.width = oldwidth;
6062 r_refdef.view.height = oldheight;
6063 r_refdef.view.colorscale = oldcolorscale;
6065 R_ResetViewRendering3D();
6067 R_ClearScreen(r_refdef.fogenabled);
6068 if (r_timereport_active)
6069 R_TimeReport("viewclear");
6072 static void R_BlendView(void)
6074 unsigned int permutation;
6075 float uservecs[4][4];
6077 switch (vid.renderpath)
6079 case RENDERPATH_GL20:
6080 case RENDERPATH_D3D9:
6081 case RENDERPATH_D3D10:
6082 case RENDERPATH_D3D11:
6083 case RENDERPATH_SOFT:
6084 case RENDERPATH_GLES2:
6086 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6087 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6088 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6089 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6090 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6092 if (r_bloomstate.texture_screen)
6094 // make sure the buffer is available
6095 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6097 R_ResetViewRendering2D();
6099 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6101 // declare variables
6103 static float avgspeed;
6105 speed = VectorLength(cl.movement_velocity);
6107 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6108 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6110 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6111 speed = bound(0, speed, 1);
6112 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6114 // calculate values into a standard alpha
6115 cl.motionbluralpha = 1 - exp(-
6117 (r_motionblur.value * speed / 80)
6119 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6122 max(0.0001, cl.time - cl.oldtime) // fps independent
6125 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6126 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6128 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6130 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6131 GL_Color(1, 1, 1, cl.motionbluralpha);
6132 switch(vid.renderpath)
6134 case RENDERPATH_GL11:
6135 case RENDERPATH_GL13:
6136 case RENDERPATH_GL20:
6137 case RENDERPATH_SOFT:
6138 case RENDERPATH_GLES2:
6139 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6141 case RENDERPATH_D3D9:
6142 case RENDERPATH_D3D10:
6143 case RENDERPATH_D3D11:
6144 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6147 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6148 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6149 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6153 // copy view into the screen texture
6154 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);
6155 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6157 else if (!r_bloomstate.texture_bloom)
6159 // we may still have to do view tint...
6160 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6162 // apply a color tint to the whole view
6163 R_ResetViewRendering2D();
6164 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6165 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6166 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6167 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6168 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6170 break; // no screen processing, no bloom, skip it
6173 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6175 // render simple bloom effect
6176 // copy the screen and shrink it and darken it for the bloom process
6177 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6178 // make the bloom texture
6179 R_Bloom_MakeTexture();
6182 #if _MSC_VER >= 1400
6183 #define sscanf sscanf_s
6185 memset(uservecs, 0, sizeof(uservecs));
6186 if (r_glsl_postprocess_uservec1_enable.integer)
6187 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6188 if (r_glsl_postprocess_uservec2_enable.integer)
6189 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6190 if (r_glsl_postprocess_uservec3_enable.integer)
6191 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6192 if (r_glsl_postprocess_uservec4_enable.integer)
6193 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6195 R_ResetViewRendering2D();
6196 GL_Color(1, 1, 1, 1);
6197 GL_BlendFunc(GL_ONE, GL_ZERO);
6199 switch(vid.renderpath)
6201 case RENDERPATH_GL20:
6202 case RENDERPATH_GLES2:
6203 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6204 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6205 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6206 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6207 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6208 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]);
6209 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6210 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]);
6211 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]);
6212 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]);
6213 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]);
6214 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6215 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6216 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);
6218 case RENDERPATH_D3D9:
6220 // 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...
6221 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6222 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6223 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6224 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6225 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6226 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6227 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6228 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6229 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6230 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6231 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6232 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6233 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6234 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6237 case RENDERPATH_D3D10:
6238 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6240 case RENDERPATH_D3D11:
6241 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6243 case RENDERPATH_SOFT:
6244 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6245 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6246 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6247 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6248 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6249 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6250 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6251 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6252 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6253 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6254 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6255 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6256 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6257 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6262 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6263 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6265 case RENDERPATH_GL13:
6266 case RENDERPATH_GL11:
6267 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6269 // apply a color tint to the whole view
6270 R_ResetViewRendering2D();
6271 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6272 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6273 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6274 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6275 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6281 matrix4x4_t r_waterscrollmatrix;
6283 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6285 if (r_refdef.fog_density)
6287 r_refdef.fogcolor[0] = r_refdef.fog_red;
6288 r_refdef.fogcolor[1] = r_refdef.fog_green;
6289 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6291 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6292 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6293 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6294 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6298 VectorCopy(r_refdef.fogcolor, fogvec);
6299 // color.rgb *= ContrastBoost * SceneBrightness;
6300 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6301 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6302 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6303 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6308 void R_UpdateVariables(void)
6312 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6314 r_refdef.farclip = r_farclip_base.value;
6315 if (r_refdef.scene.worldmodel)
6316 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6317 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6319 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6320 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6321 r_refdef.polygonfactor = 0;
6322 r_refdef.polygonoffset = 0;
6323 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6324 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6326 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6327 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6328 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6329 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6330 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6331 if (FAKELIGHT_ENABLED)
6333 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6335 if (r_showsurfaces.integer)
6337 r_refdef.scene.rtworld = false;
6338 r_refdef.scene.rtworldshadows = false;
6339 r_refdef.scene.rtdlight = false;
6340 r_refdef.scene.rtdlightshadows = false;
6341 r_refdef.lightmapintensity = 0;
6344 if (gamemode == GAME_NEHAHRA)
6346 if (gl_fogenable.integer)
6348 r_refdef.oldgl_fogenable = true;
6349 r_refdef.fog_density = gl_fogdensity.value;
6350 r_refdef.fog_red = gl_fogred.value;
6351 r_refdef.fog_green = gl_foggreen.value;
6352 r_refdef.fog_blue = gl_fogblue.value;
6353 r_refdef.fog_alpha = 1;
6354 r_refdef.fog_start = 0;
6355 r_refdef.fog_end = gl_skyclip.value;
6356 r_refdef.fog_height = 1<<30;
6357 r_refdef.fog_fadedepth = 128;
6359 else if (r_refdef.oldgl_fogenable)
6361 r_refdef.oldgl_fogenable = false;
6362 r_refdef.fog_density = 0;
6363 r_refdef.fog_red = 0;
6364 r_refdef.fog_green = 0;
6365 r_refdef.fog_blue = 0;
6366 r_refdef.fog_alpha = 0;
6367 r_refdef.fog_start = 0;
6368 r_refdef.fog_end = 0;
6369 r_refdef.fog_height = 1<<30;
6370 r_refdef.fog_fadedepth = 128;
6374 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6375 r_refdef.fog_start = max(0, r_refdef.fog_start);
6376 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6378 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6380 if (r_refdef.fog_density && r_drawfog.integer)
6382 r_refdef.fogenabled = true;
6383 // this is the point where the fog reaches 0.9986 alpha, which we
6384 // consider a good enough cutoff point for the texture
6385 // (0.9986 * 256 == 255.6)
6386 if (r_fog_exp2.integer)
6387 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6389 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6390 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6391 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6392 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6393 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6394 R_BuildFogHeightTexture();
6395 // fog color was already set
6396 // update the fog texture
6397 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)
6398 R_BuildFogTexture();
6399 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6400 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6403 r_refdef.fogenabled = false;
6405 switch(vid.renderpath)
6407 case RENDERPATH_GL20:
6408 case RENDERPATH_D3D9:
6409 case RENDERPATH_D3D10:
6410 case RENDERPATH_D3D11:
6411 case RENDERPATH_SOFT:
6412 case RENDERPATH_GLES2:
6413 if(v_glslgamma.integer && !vid_gammatables_trivial)
6415 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6417 // build GLSL gamma texture
6418 #define RAMPWIDTH 256
6419 unsigned short ramp[RAMPWIDTH * 3];
6420 unsigned char rampbgr[RAMPWIDTH][4];
6423 r_texture_gammaramps_serial = vid_gammatables_serial;
6425 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6426 for(i = 0; i < RAMPWIDTH; ++i)
6428 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6429 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6430 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6433 if (r_texture_gammaramps)
6435 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6439 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6445 // remove GLSL gamma texture
6448 case RENDERPATH_GL13:
6449 case RENDERPATH_GL11:
6454 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6455 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6461 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6462 if( scenetype != r_currentscenetype ) {
6463 // store the old scenetype
6464 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6465 r_currentscenetype = scenetype;
6466 // move in the new scene
6467 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6476 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6478 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6479 if( scenetype == r_currentscenetype ) {
6480 return &r_refdef.scene;
6482 return &r_scenes_store[ scenetype ];
6491 int dpsoftrast_test;
6492 void R_RenderView(void)
6494 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6496 dpsoftrast_test = r_test.integer;
6498 if (r_timereport_active)
6499 R_TimeReport("start");
6500 r_textureframe++; // used only by R_GetCurrentTexture
6501 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6503 if(R_CompileShader_CheckStaticParms())
6506 if (!r_drawentities.integer)
6507 r_refdef.scene.numentities = 0;
6509 R_AnimCache_ClearCache();
6510 R_FrameData_NewFrame();
6512 /* adjust for stereo display */
6513 if(R_Stereo_Active())
6515 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);
6516 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6519 if (r_refdef.view.isoverlay)
6521 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6522 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6523 R_TimeReport("depthclear");
6525 r_refdef.view.showdebug = false;
6527 r_waterstate.enabled = false;
6528 r_waterstate.numwaterplanes = 0;
6532 r_refdef.view.matrix = originalmatrix;
6538 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6540 r_refdef.view.matrix = originalmatrix;
6541 return; //Host_Error ("R_RenderView: NULL worldmodel");
6544 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6546 R_RenderView_UpdateViewVectors();
6548 R_Shadow_UpdateWorldLightSelection();
6550 R_Bloom_StartFrame();
6551 R_Water_StartFrame();
6554 if (r_timereport_active)
6555 R_TimeReport("viewsetup");
6557 R_ResetViewRendering3D();
6559 if (r_refdef.view.clear || r_refdef.fogenabled)
6561 R_ClearScreen(r_refdef.fogenabled);
6562 if (r_timereport_active)
6563 R_TimeReport("viewclear");
6565 r_refdef.view.clear = true;
6567 // this produces a bloom texture to be used in R_BlendView() later
6568 if (r_hdr.integer && r_bloomstate.bloomwidth)
6570 R_HDR_RenderBloomTexture();
6571 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6572 r_textureframe++; // used only by R_GetCurrentTexture
6575 r_refdef.view.showdebug = true;
6578 if (r_timereport_active)
6579 R_TimeReport("visibility");
6581 r_waterstate.numwaterplanes = 0;
6582 if (r_waterstate.enabled)
6583 R_RenderWaterPlanes();
6586 r_waterstate.numwaterplanes = 0;
6589 if (r_timereport_active)
6590 R_TimeReport("blendview");
6592 GL_Scissor(0, 0, vid.width, vid.height);
6593 GL_ScissorTest(false);
6595 r_refdef.view.matrix = originalmatrix;
6600 void R_RenderWaterPlanes(void)
6602 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6604 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6605 if (r_timereport_active)
6606 R_TimeReport("waterworld");
6609 // don't let sound skip if going slow
6610 if (r_refdef.scene.extraupdate)
6613 R_DrawModelsAddWaterPlanes();
6614 if (r_timereport_active)
6615 R_TimeReport("watermodels");
6617 if (r_waterstate.numwaterplanes)
6619 R_Water_ProcessPlanes();
6620 if (r_timereport_active)
6621 R_TimeReport("waterscenes");
6625 extern void R_DrawLightningBeams (void);
6626 extern void VM_CL_AddPolygonsToMeshQueue (void);
6627 extern void R_DrawPortals (void);
6628 extern cvar_t cl_locs_show;
6629 static void R_DrawLocs(void);
6630 static void R_DrawEntityBBoxes(void);
6631 static void R_DrawModelDecals(void);
6632 extern void R_DrawModelShadows(void);
6633 extern void R_DrawModelShadowMaps(void);
6634 extern cvar_t cl_decals_newsystem;
6635 extern qboolean r_shadow_usingdeferredprepass;
6636 void R_RenderScene(void)
6638 qboolean shadowmapping = false;
6640 if (r_timereport_active)
6641 R_TimeReport("beginscene");
6643 r_refdef.stats.renders++;
6647 // don't let sound skip if going slow
6648 if (r_refdef.scene.extraupdate)
6651 R_MeshQueue_BeginScene();
6655 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);
6657 if (r_timereport_active)
6658 R_TimeReport("skystartframe");
6660 if (cl.csqc_vidvars.drawworld)
6662 // don't let sound skip if going slow
6663 if (r_refdef.scene.extraupdate)
6666 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6668 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6669 if (r_timereport_active)
6670 R_TimeReport("worldsky");
6673 if (R_DrawBrushModelsSky() && r_timereport_active)
6674 R_TimeReport("bmodelsky");
6676 if (skyrendermasked && skyrenderlater)
6678 // we have to force off the water clipping plane while rendering sky
6682 if (r_timereport_active)
6683 R_TimeReport("sky");
6687 R_AnimCache_CacheVisibleEntities();
6688 if (r_timereport_active)
6689 R_TimeReport("animation");
6691 R_Shadow_PrepareLights();
6692 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6693 R_Shadow_PrepareModelShadows();
6694 if (r_timereport_active)
6695 R_TimeReport("preparelights");
6697 if (R_Shadow_ShadowMappingEnabled())
6698 shadowmapping = true;
6700 if (r_shadow_usingdeferredprepass)
6701 R_Shadow_DrawPrepass();
6703 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6705 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6706 if (r_timereport_active)
6707 R_TimeReport("worlddepth");
6709 if (r_depthfirst.integer >= 2)
6711 R_DrawModelsDepth();
6712 if (r_timereport_active)
6713 R_TimeReport("modeldepth");
6716 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6718 R_DrawModelShadowMaps();
6719 R_ResetViewRendering3D();
6720 // don't let sound skip if going slow
6721 if (r_refdef.scene.extraupdate)
6725 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6727 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6728 if (r_timereport_active)
6729 R_TimeReport("world");
6732 // don't let sound skip if going slow
6733 if (r_refdef.scene.extraupdate)
6737 if (r_timereport_active)
6738 R_TimeReport("models");
6740 // don't let sound skip if going slow
6741 if (r_refdef.scene.extraupdate)
6744 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6746 R_DrawModelShadows();
6747 R_ResetViewRendering3D();
6748 // don't let sound skip if going slow
6749 if (r_refdef.scene.extraupdate)
6753 if (!r_shadow_usingdeferredprepass)
6755 R_Shadow_DrawLights();
6756 if (r_timereport_active)
6757 R_TimeReport("rtlights");
6760 // don't let sound skip if going slow
6761 if (r_refdef.scene.extraupdate)
6764 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6766 R_DrawModelShadows();
6767 R_ResetViewRendering3D();
6768 // don't let sound skip if going slow
6769 if (r_refdef.scene.extraupdate)
6773 if (cl.csqc_vidvars.drawworld)
6775 if (cl_decals_newsystem.integer)
6777 R_DrawModelDecals();
6778 if (r_timereport_active)
6779 R_TimeReport("modeldecals");
6784 if (r_timereport_active)
6785 R_TimeReport("decals");
6789 if (r_timereport_active)
6790 R_TimeReport("particles");
6793 if (r_timereport_active)
6794 R_TimeReport("explosions");
6796 R_DrawLightningBeams();
6797 if (r_timereport_active)
6798 R_TimeReport("lightning");
6801 VM_CL_AddPolygonsToMeshQueue();
6803 if (r_refdef.view.showdebug)
6805 if (cl_locs_show.integer)
6808 if (r_timereport_active)
6809 R_TimeReport("showlocs");
6812 if (r_drawportals.integer)
6815 if (r_timereport_active)
6816 R_TimeReport("portals");
6819 if (r_showbboxes.value > 0)
6821 R_DrawEntityBBoxes();
6822 if (r_timereport_active)
6823 R_TimeReport("bboxes");
6827 R_MeshQueue_RenderTransparent();
6828 if (r_timereport_active)
6829 R_TimeReport("drawtrans");
6831 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))
6833 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6834 if (r_timereport_active)
6835 R_TimeReport("worlddebug");
6836 R_DrawModelsDebug();
6837 if (r_timereport_active)
6838 R_TimeReport("modeldebug");
6841 if (cl.csqc_vidvars.drawworld)
6843 R_Shadow_DrawCoronas();
6844 if (r_timereport_active)
6845 R_TimeReport("coronas");
6850 GL_DepthTest(false);
6851 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6852 GL_Color(1, 1, 1, 1);
6853 qglBegin(GL_POLYGON);
6854 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6855 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6856 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6857 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6859 qglBegin(GL_POLYGON);
6860 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]);
6861 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]);
6862 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]);
6863 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]);
6865 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6869 // don't let sound skip if going slow
6870 if (r_refdef.scene.extraupdate)
6873 R_ResetViewRendering2D();
6876 static const unsigned short bboxelements[36] =
6886 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6889 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6891 RSurf_ActiveWorldEntity();
6893 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6894 GL_DepthMask(false);
6895 GL_DepthRange(0, 1);
6896 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6897 // R_Mesh_ResetTextureState();
6899 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6900 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6901 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6902 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6903 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6904 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6905 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6906 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6907 R_FillColors(color4f, 8, cr, cg, cb, ca);
6908 if (r_refdef.fogenabled)
6910 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6912 f1 = RSurf_FogVertex(v);
6914 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6915 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6916 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6919 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6920 R_Mesh_ResetTextureState();
6921 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6922 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6925 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6929 prvm_edict_t *edict;
6930 prvm_prog_t *prog_save = prog;
6932 // this function draws bounding boxes of server entities
6936 GL_CullFace(GL_NONE);
6937 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6941 for (i = 0;i < numsurfaces;i++)
6943 edict = PRVM_EDICT_NUM(surfacelist[i]);
6944 switch ((int)edict->fields.server->solid)
6946 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
6947 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
6948 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
6949 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6950 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
6951 default: Vector4Set(color, 0, 0, 0, 0.50);break;
6953 color[3] *= r_showbboxes.value;
6954 color[3] = bound(0, color[3], 1);
6955 GL_DepthTest(!r_showdisabledepthtest.integer);
6956 GL_CullFace(r_refdef.view.cullface_front);
6957 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6963 static void R_DrawEntityBBoxes(void)
6966 prvm_edict_t *edict;
6968 prvm_prog_t *prog_save = prog;
6970 // this function draws bounding boxes of server entities
6976 for (i = 0;i < prog->num_edicts;i++)
6978 edict = PRVM_EDICT_NUM(i);
6979 if (edict->priv.server->free)
6981 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6982 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
6984 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
6986 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
6987 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
6993 static const int nomodelelement3i[24] =
7005 static const unsigned short nomodelelement3s[24] =
7017 static const float nomodelvertex3f[6*3] =
7027 static const float nomodelcolor4f[6*4] =
7029 0.0f, 0.0f, 0.5f, 1.0f,
7030 0.0f, 0.0f, 0.5f, 1.0f,
7031 0.0f, 0.5f, 0.0f, 1.0f,
7032 0.0f, 0.5f, 0.0f, 1.0f,
7033 0.5f, 0.0f, 0.0f, 1.0f,
7034 0.5f, 0.0f, 0.0f, 1.0f
7037 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7043 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);
7045 // this is only called once per entity so numsurfaces is always 1, and
7046 // surfacelist is always {0}, so this code does not handle batches
7048 if (rsurface.ent_flags & RENDER_ADDITIVE)
7050 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7051 GL_DepthMask(false);
7053 else if (rsurface.colormod[3] < 1)
7055 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7056 GL_DepthMask(false);
7060 GL_BlendFunc(GL_ONE, GL_ZERO);
7063 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7064 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7065 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7066 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7067 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7068 for (i = 0, c = color4f;i < 6;i++, c += 4)
7070 c[0] *= rsurface.colormod[0];
7071 c[1] *= rsurface.colormod[1];
7072 c[2] *= rsurface.colormod[2];
7073 c[3] *= rsurface.colormod[3];
7075 if (r_refdef.fogenabled)
7077 for (i = 0, c = color4f;i < 6;i++, c += 4)
7079 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7081 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7082 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7083 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7086 // R_Mesh_ResetTextureState();
7087 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7088 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7089 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7092 void R_DrawNoModel(entity_render_t *ent)
7095 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7096 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7097 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7099 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7102 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7104 vec3_t right1, right2, diff, normal;
7106 VectorSubtract (org2, org1, normal);
7108 // calculate 'right' vector for start
7109 VectorSubtract (r_refdef.view.origin, org1, diff);
7110 CrossProduct (normal, diff, right1);
7111 VectorNormalize (right1);
7113 // calculate 'right' vector for end
7114 VectorSubtract (r_refdef.view.origin, org2, diff);
7115 CrossProduct (normal, diff, right2);
7116 VectorNormalize (right2);
7118 vert[ 0] = org1[0] + width * right1[0];
7119 vert[ 1] = org1[1] + width * right1[1];
7120 vert[ 2] = org1[2] + width * right1[2];
7121 vert[ 3] = org1[0] - width * right1[0];
7122 vert[ 4] = org1[1] - width * right1[1];
7123 vert[ 5] = org1[2] - width * right1[2];
7124 vert[ 6] = org2[0] - width * right2[0];
7125 vert[ 7] = org2[1] - width * right2[1];
7126 vert[ 8] = org2[2] - width * right2[2];
7127 vert[ 9] = org2[0] + width * right2[0];
7128 vert[10] = org2[1] + width * right2[1];
7129 vert[11] = org2[2] + width * right2[2];
7132 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)
7134 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7135 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7136 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7137 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7138 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7139 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7140 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7141 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7142 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7143 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7144 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7145 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7148 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7153 VectorSet(v, x, y, z);
7154 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7155 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7157 if (i == mesh->numvertices)
7159 if (mesh->numvertices < mesh->maxvertices)
7161 VectorCopy(v, vertex3f);
7162 mesh->numvertices++;
7164 return mesh->numvertices;
7170 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7174 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7175 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7176 e = mesh->element3i + mesh->numtriangles * 3;
7177 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7179 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7180 if (mesh->numtriangles < mesh->maxtriangles)
7185 mesh->numtriangles++;
7187 element[1] = element[2];
7191 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7195 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7196 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7197 e = mesh->element3i + mesh->numtriangles * 3;
7198 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7200 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7201 if (mesh->numtriangles < mesh->maxtriangles)
7206 mesh->numtriangles++;
7208 element[1] = element[2];
7212 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7213 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7215 int planenum, planenum2;
7218 mplane_t *plane, *plane2;
7220 double temppoints[2][256*3];
7221 // figure out how large a bounding box we need to properly compute this brush
7223 for (w = 0;w < numplanes;w++)
7224 maxdist = max(maxdist, fabs(planes[w].dist));
7225 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7226 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7227 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7231 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7232 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7234 if (planenum2 == planenum)
7236 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);
7239 if (tempnumpoints < 3)
7241 // generate elements forming a triangle fan for this polygon
7242 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7246 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)
7248 texturelayer_t *layer;
7249 layer = t->currentlayers + t->currentnumlayers++;
7251 layer->depthmask = depthmask;
7252 layer->blendfunc1 = blendfunc1;
7253 layer->blendfunc2 = blendfunc2;
7254 layer->texture = texture;
7255 layer->texmatrix = *matrix;
7256 layer->color[0] = r;
7257 layer->color[1] = g;
7258 layer->color[2] = b;
7259 layer->color[3] = a;
7262 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7264 if(parms[0] == 0 && parms[1] == 0)
7266 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7267 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7272 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7275 index = parms[2] + r_refdef.scene.time * parms[3];
7276 index -= floor(index);
7277 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7280 case Q3WAVEFUNC_NONE:
7281 case Q3WAVEFUNC_NOISE:
7282 case Q3WAVEFUNC_COUNT:
7285 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7286 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7287 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7288 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7289 case Q3WAVEFUNC_TRIANGLE:
7291 f = index - floor(index);
7302 f = parms[0] + parms[1] * f;
7303 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7304 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7308 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7313 matrix4x4_t matrix, temp;
7314 switch(tcmod->tcmod)
7318 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7319 matrix = r_waterscrollmatrix;
7321 matrix = identitymatrix;
7323 case Q3TCMOD_ENTITYTRANSLATE:
7324 // this is used in Q3 to allow the gamecode to control texcoord
7325 // scrolling on the entity, which is not supported in darkplaces yet.
7326 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7328 case Q3TCMOD_ROTATE:
7329 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7330 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7331 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7334 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7336 case Q3TCMOD_SCROLL:
7337 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7339 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7340 w = (int) tcmod->parms[0];
7341 h = (int) tcmod->parms[1];
7342 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7344 idx = (int) floor(f * w * h);
7345 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7347 case Q3TCMOD_STRETCH:
7348 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7349 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7351 case Q3TCMOD_TRANSFORM:
7352 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7353 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7354 VectorSet(tcmat + 6, 0 , 0 , 1);
7355 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7356 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7358 case Q3TCMOD_TURBULENT:
7359 // this is handled in the RSurf_PrepareVertices function
7360 matrix = identitymatrix;
7364 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7367 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7369 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7370 char name[MAX_QPATH];
7371 skinframe_t *skinframe;
7372 unsigned char pixels[296*194];
7373 strlcpy(cache->name, skinname, sizeof(cache->name));
7374 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7375 if (developer_loading.integer)
7376 Con_Printf("loading %s\n", name);
7377 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7378 if (!skinframe || !skinframe->base)
7381 fs_offset_t filesize;
7383 f = FS_LoadFile(name, tempmempool, true, &filesize);
7386 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7387 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7391 cache->skinframe = skinframe;
7394 texture_t *R_GetCurrentTexture(texture_t *t)
7397 const entity_render_t *ent = rsurface.entity;
7398 dp_model_t *model = ent->model;
7399 q3shaderinfo_layer_tcmod_t *tcmod;
7401 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7402 return t->currentframe;
7403 t->update_lastrenderframe = r_textureframe;
7404 t->update_lastrenderentity = (void *)ent;
7406 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7407 t->camera_entity = ent->entitynumber;
7409 t->camera_entity = 0;
7411 // switch to an alternate material if this is a q1bsp animated material
7413 texture_t *texture = t;
7414 int s = rsurface.ent_skinnum;
7415 if ((unsigned int)s >= (unsigned int)model->numskins)
7417 if (model->skinscenes)
7419 if (model->skinscenes[s].framecount > 1)
7420 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7422 s = model->skinscenes[s].firstframe;
7425 t = t + s * model->num_surfaces;
7428 // use an alternate animation if the entity's frame is not 0,
7429 // and only if the texture has an alternate animation
7430 if (rsurface.ent_alttextures && t->anim_total[1])
7431 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7433 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7435 texture->currentframe = t;
7438 // update currentskinframe to be a qw skin or animation frame
7439 if (rsurface.ent_qwskin >= 0)
7441 i = rsurface.ent_qwskin;
7442 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7444 r_qwskincache_size = cl.maxclients;
7446 Mem_Free(r_qwskincache);
7447 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7449 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7450 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7451 t->currentskinframe = r_qwskincache[i].skinframe;
7452 if (t->currentskinframe == NULL)
7453 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7455 else if (t->numskinframes >= 2)
7456 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7457 if (t->backgroundnumskinframes >= 2)
7458 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7460 t->currentmaterialflags = t->basematerialflags;
7461 t->currentalpha = rsurface.colormod[3];
7462 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7463 t->currentalpha *= r_wateralpha.value;
7464 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7465 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7466 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7467 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7468 if (!(rsurface.ent_flags & RENDER_LIGHT))
7469 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7470 else if (FAKELIGHT_ENABLED)
7472 // no modellight if using fakelight for the map
7474 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7476 // pick a model lighting mode
7477 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7478 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7480 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7482 if (rsurface.ent_flags & RENDER_ADDITIVE)
7483 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7484 else if (t->currentalpha < 1)
7485 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7486 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7487 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7488 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7489 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7490 if (t->backgroundnumskinframes)
7491 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7492 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7494 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7495 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7498 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7499 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7500 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7502 // there is no tcmod
7503 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7505 t->currenttexmatrix = r_waterscrollmatrix;
7506 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7508 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7510 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7511 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7514 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7515 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7516 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7517 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7519 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7520 if (t->currentskinframe->qpixels)
7521 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7522 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7523 if (!t->basetexture)
7524 t->basetexture = r_texture_notexture;
7525 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7526 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7527 t->nmaptexture = t->currentskinframe->nmap;
7528 if (!t->nmaptexture)
7529 t->nmaptexture = r_texture_blanknormalmap;
7530 t->glosstexture = r_texture_black;
7531 t->glowtexture = t->currentskinframe->glow;
7532 t->fogtexture = t->currentskinframe->fog;
7533 t->reflectmasktexture = t->currentskinframe->reflect;
7534 if (t->backgroundnumskinframes)
7536 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7537 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7538 t->backgroundglosstexture = r_texture_black;
7539 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7540 if (!t->backgroundnmaptexture)
7541 t->backgroundnmaptexture = r_texture_blanknormalmap;
7545 t->backgroundbasetexture = r_texture_white;
7546 t->backgroundnmaptexture = r_texture_blanknormalmap;
7547 t->backgroundglosstexture = r_texture_black;
7548 t->backgroundglowtexture = NULL;
7550 t->specularpower = r_shadow_glossexponent.value;
7551 // TODO: store reference values for these in the texture?
7552 t->specularscale = 0;
7553 if (r_shadow_gloss.integer > 0)
7555 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7557 if (r_shadow_glossintensity.value > 0)
7559 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7560 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7561 t->specularscale = r_shadow_glossintensity.value;
7564 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7566 t->glosstexture = r_texture_white;
7567 t->backgroundglosstexture = r_texture_white;
7568 t->specularscale = r_shadow_gloss2intensity.value;
7569 t->specularpower = r_shadow_gloss2exponent.value;
7572 t->specularscale *= t->specularscalemod;
7573 t->specularpower *= t->specularpowermod;
7575 // lightmaps mode looks bad with dlights using actual texturing, so turn
7576 // off the colormap and glossmap, but leave the normalmap on as it still
7577 // accurately represents the shading involved
7578 if (gl_lightmaps.integer)
7580 t->basetexture = r_texture_grey128;
7581 t->pantstexture = r_texture_black;
7582 t->shirttexture = r_texture_black;
7583 t->nmaptexture = r_texture_blanknormalmap;
7584 t->glosstexture = r_texture_black;
7585 t->glowtexture = NULL;
7586 t->fogtexture = NULL;
7587 t->reflectmasktexture = NULL;
7588 t->backgroundbasetexture = NULL;
7589 t->backgroundnmaptexture = r_texture_blanknormalmap;
7590 t->backgroundglosstexture = r_texture_black;
7591 t->backgroundglowtexture = NULL;
7592 t->specularscale = 0;
7593 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7596 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7597 VectorClear(t->dlightcolor);
7598 t->currentnumlayers = 0;
7599 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7601 int blendfunc1, blendfunc2;
7603 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7605 blendfunc1 = GL_SRC_ALPHA;
7606 blendfunc2 = GL_ONE;
7608 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7610 blendfunc1 = GL_SRC_ALPHA;
7611 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7613 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7615 blendfunc1 = t->customblendfunc[0];
7616 blendfunc2 = t->customblendfunc[1];
7620 blendfunc1 = GL_ONE;
7621 blendfunc2 = GL_ZERO;
7623 // don't colormod evilblend textures
7624 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
7625 VectorSet(t->lightmapcolor, 1, 1, 1);
7626 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7627 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7629 // fullbright is not affected by r_refdef.lightmapintensity
7630 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]);
7631 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7632 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]);
7633 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7634 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]);
7638 vec3_t ambientcolor;
7640 // set the color tint used for lights affecting this surface
7641 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7643 // q3bsp has no lightmap updates, so the lightstylevalue that
7644 // would normally be baked into the lightmap must be
7645 // applied to the color
7646 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7647 if (model->type == mod_brushq3)
7648 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7649 colorscale *= r_refdef.lightmapintensity;
7650 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7651 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7652 // basic lit geometry
7653 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]);
7654 // add pants/shirt if needed
7655 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7656 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]);
7657 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7658 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]);
7659 // now add ambient passes if needed
7660 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7662 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]);
7663 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7664 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]);
7665 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7666 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]);
7669 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7670 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]);
7671 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7673 // if this is opaque use alpha blend which will darken the earlier
7676 // if this is an alpha blended material, all the earlier passes
7677 // were darkened by fog already, so we only need to add the fog
7678 // color ontop through the fog mask texture
7680 // if this is an additive blended material, all the earlier passes
7681 // were darkened by fog already, and we should not add fog color
7682 // (because the background was not darkened, there is no fog color
7683 // that was lost behind it).
7684 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]);
7688 return t->currentframe;
7691 rsurfacestate_t rsurface;
7693 void RSurf_ActiveWorldEntity(void)
7695 dp_model_t *model = r_refdef.scene.worldmodel;
7696 //if (rsurface.entity == r_refdef.scene.worldentity)
7698 rsurface.entity = r_refdef.scene.worldentity;
7699 rsurface.skeleton = NULL;
7700 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7701 rsurface.ent_skinnum = 0;
7702 rsurface.ent_qwskin = -1;
7703 rsurface.ent_shadertime = 0;
7704 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7705 rsurface.matrix = identitymatrix;
7706 rsurface.inversematrix = identitymatrix;
7707 rsurface.matrixscale = 1;
7708 rsurface.inversematrixscale = 1;
7709 R_EntityMatrix(&identitymatrix);
7710 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7711 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7712 rsurface.fograngerecip = r_refdef.fograngerecip;
7713 rsurface.fogheightfade = r_refdef.fogheightfade;
7714 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7715 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7716 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7717 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7718 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7719 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7720 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7721 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7722 rsurface.colormod[3] = 1;
7723 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);
7724 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7725 rsurface.frameblend[0].lerp = 1;
7726 rsurface.ent_alttextures = false;
7727 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7728 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7729 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7730 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7731 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7732 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7733 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7734 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7735 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7736 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7737 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7738 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7739 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7740 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7741 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7742 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7743 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7744 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7745 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7746 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7747 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7748 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7749 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7750 rsurface.modelelement3i = model->surfmesh.data_element3i;
7751 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7752 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7753 rsurface.modelelement3s = model->surfmesh.data_element3s;
7754 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7755 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7756 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7757 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7758 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7759 rsurface.modelsurfaces = model->data_surfaces;
7760 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7761 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7762 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7763 rsurface.modelgeneratedvertex = false;
7764 rsurface.batchgeneratedvertex = false;
7765 rsurface.batchfirstvertex = 0;
7766 rsurface.batchnumvertices = 0;
7767 rsurface.batchfirsttriangle = 0;
7768 rsurface.batchnumtriangles = 0;
7769 rsurface.batchvertex3f = NULL;
7770 rsurface.batchvertex3f_vertexbuffer = NULL;
7771 rsurface.batchvertex3f_bufferoffset = 0;
7772 rsurface.batchsvector3f = NULL;
7773 rsurface.batchsvector3f_vertexbuffer = NULL;
7774 rsurface.batchsvector3f_bufferoffset = 0;
7775 rsurface.batchtvector3f = NULL;
7776 rsurface.batchtvector3f_vertexbuffer = NULL;
7777 rsurface.batchtvector3f_bufferoffset = 0;
7778 rsurface.batchnormal3f = NULL;
7779 rsurface.batchnormal3f_vertexbuffer = NULL;
7780 rsurface.batchnormal3f_bufferoffset = 0;
7781 rsurface.batchlightmapcolor4f = NULL;
7782 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7783 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7784 rsurface.batchtexcoordtexture2f = NULL;
7785 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7786 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7787 rsurface.batchtexcoordlightmap2f = NULL;
7788 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7789 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7790 rsurface.batchvertexmesh = NULL;
7791 rsurface.batchvertexmeshbuffer = NULL;
7792 rsurface.batchvertex3fbuffer = NULL;
7793 rsurface.batchelement3i = NULL;
7794 rsurface.batchelement3i_indexbuffer = NULL;
7795 rsurface.batchelement3i_bufferoffset = 0;
7796 rsurface.batchelement3s = NULL;
7797 rsurface.batchelement3s_indexbuffer = NULL;
7798 rsurface.batchelement3s_bufferoffset = 0;
7799 rsurface.passcolor4f = NULL;
7800 rsurface.passcolor4f_vertexbuffer = NULL;
7801 rsurface.passcolor4f_bufferoffset = 0;
7804 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7806 dp_model_t *model = ent->model;
7807 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7809 rsurface.entity = (entity_render_t *)ent;
7810 rsurface.skeleton = ent->skeleton;
7811 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7812 rsurface.ent_skinnum = ent->skinnum;
7813 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;
7814 rsurface.ent_shadertime = ent->shadertime;
7815 rsurface.ent_flags = ent->flags;
7816 rsurface.matrix = ent->matrix;
7817 rsurface.inversematrix = ent->inversematrix;
7818 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7819 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7820 R_EntityMatrix(&rsurface.matrix);
7821 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7822 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7823 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7824 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7825 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7826 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7827 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7828 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7829 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7830 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7831 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7832 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7833 rsurface.colormod[3] = ent->alpha;
7834 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7835 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7836 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7837 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7838 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7839 if (ent->model->brush.submodel && !prepass)
7841 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7842 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7844 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7846 if (ent->animcache_vertex3f)
7848 rsurface.modelvertex3f = ent->animcache_vertex3f;
7849 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7850 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7851 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7852 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7853 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7854 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7856 else if (wanttangents)
7858 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7859 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7860 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7861 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7862 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7863 rsurface.modelvertexmesh = NULL;
7864 rsurface.modelvertexmeshbuffer = NULL;
7865 rsurface.modelvertex3fbuffer = NULL;
7867 else if (wantnormals)
7869 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7870 rsurface.modelsvector3f = NULL;
7871 rsurface.modeltvector3f = NULL;
7872 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7873 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7874 rsurface.modelvertexmesh = NULL;
7875 rsurface.modelvertexmeshbuffer = NULL;
7876 rsurface.modelvertex3fbuffer = NULL;
7880 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7881 rsurface.modelsvector3f = NULL;
7882 rsurface.modeltvector3f = NULL;
7883 rsurface.modelnormal3f = NULL;
7884 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7885 rsurface.modelvertexmesh = NULL;
7886 rsurface.modelvertexmeshbuffer = NULL;
7887 rsurface.modelvertex3fbuffer = NULL;
7889 rsurface.modelvertex3f_vertexbuffer = 0;
7890 rsurface.modelvertex3f_bufferoffset = 0;
7891 rsurface.modelsvector3f_vertexbuffer = 0;
7892 rsurface.modelsvector3f_bufferoffset = 0;
7893 rsurface.modeltvector3f_vertexbuffer = 0;
7894 rsurface.modeltvector3f_bufferoffset = 0;
7895 rsurface.modelnormal3f_vertexbuffer = 0;
7896 rsurface.modelnormal3f_bufferoffset = 0;
7897 rsurface.modelgeneratedvertex = true;
7901 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7902 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7903 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7904 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7905 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7906 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7907 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7908 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7909 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7910 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7911 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7912 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7913 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7914 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7915 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7916 rsurface.modelgeneratedvertex = false;
7918 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7919 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7920 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7921 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7922 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7923 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7924 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7925 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7926 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7927 rsurface.modelelement3i = model->surfmesh.data_element3i;
7928 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7929 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7930 rsurface.modelelement3s = model->surfmesh.data_element3s;
7931 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7932 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7933 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7934 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7935 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7936 rsurface.modelsurfaces = model->data_surfaces;
7937 rsurface.batchgeneratedvertex = false;
7938 rsurface.batchfirstvertex = 0;
7939 rsurface.batchnumvertices = 0;
7940 rsurface.batchfirsttriangle = 0;
7941 rsurface.batchnumtriangles = 0;
7942 rsurface.batchvertex3f = NULL;
7943 rsurface.batchvertex3f_vertexbuffer = NULL;
7944 rsurface.batchvertex3f_bufferoffset = 0;
7945 rsurface.batchsvector3f = NULL;
7946 rsurface.batchsvector3f_vertexbuffer = NULL;
7947 rsurface.batchsvector3f_bufferoffset = 0;
7948 rsurface.batchtvector3f = NULL;
7949 rsurface.batchtvector3f_vertexbuffer = NULL;
7950 rsurface.batchtvector3f_bufferoffset = 0;
7951 rsurface.batchnormal3f = NULL;
7952 rsurface.batchnormal3f_vertexbuffer = NULL;
7953 rsurface.batchnormal3f_bufferoffset = 0;
7954 rsurface.batchlightmapcolor4f = NULL;
7955 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7956 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7957 rsurface.batchtexcoordtexture2f = NULL;
7958 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7959 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7960 rsurface.batchtexcoordlightmap2f = NULL;
7961 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7962 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7963 rsurface.batchvertexmesh = NULL;
7964 rsurface.batchvertexmeshbuffer = NULL;
7965 rsurface.batchvertex3fbuffer = NULL;
7966 rsurface.batchelement3i = NULL;
7967 rsurface.batchelement3i_indexbuffer = NULL;
7968 rsurface.batchelement3i_bufferoffset = 0;
7969 rsurface.batchelement3s = NULL;
7970 rsurface.batchelement3s_indexbuffer = NULL;
7971 rsurface.batchelement3s_bufferoffset = 0;
7972 rsurface.passcolor4f = NULL;
7973 rsurface.passcolor4f_vertexbuffer = NULL;
7974 rsurface.passcolor4f_bufferoffset = 0;
7977 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)
7979 rsurface.entity = r_refdef.scene.worldentity;
7980 rsurface.skeleton = NULL;
7981 rsurface.ent_skinnum = 0;
7982 rsurface.ent_qwskin = -1;
7983 rsurface.ent_shadertime = shadertime;
7984 rsurface.ent_flags = entflags;
7985 rsurface.modelnumvertices = numvertices;
7986 rsurface.modelnumtriangles = numtriangles;
7987 rsurface.matrix = *matrix;
7988 rsurface.inversematrix = *inversematrix;
7989 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7990 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7991 R_EntityMatrix(&rsurface.matrix);
7992 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7993 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7994 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7995 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7996 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7997 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7998 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7999 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8000 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8001 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8002 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8003 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8004 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);
8005 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8006 rsurface.frameblend[0].lerp = 1;
8007 rsurface.ent_alttextures = false;
8008 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8009 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8012 rsurface.modelvertex3f = (float *)vertex3f;
8013 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8014 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8015 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8017 else if (wantnormals)
8019 rsurface.modelvertex3f = (float *)vertex3f;
8020 rsurface.modelsvector3f = NULL;
8021 rsurface.modeltvector3f = NULL;
8022 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8026 rsurface.modelvertex3f = (float *)vertex3f;
8027 rsurface.modelsvector3f = NULL;
8028 rsurface.modeltvector3f = NULL;
8029 rsurface.modelnormal3f = NULL;
8031 rsurface.modelvertexmesh = NULL;
8032 rsurface.modelvertexmeshbuffer = NULL;
8033 rsurface.modelvertex3fbuffer = NULL;
8034 rsurface.modelvertex3f_vertexbuffer = 0;
8035 rsurface.modelvertex3f_bufferoffset = 0;
8036 rsurface.modelsvector3f_vertexbuffer = 0;
8037 rsurface.modelsvector3f_bufferoffset = 0;
8038 rsurface.modeltvector3f_vertexbuffer = 0;
8039 rsurface.modeltvector3f_bufferoffset = 0;
8040 rsurface.modelnormal3f_vertexbuffer = 0;
8041 rsurface.modelnormal3f_bufferoffset = 0;
8042 rsurface.modelgeneratedvertex = true;
8043 rsurface.modellightmapcolor4f = (float *)color4f;
8044 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8045 rsurface.modellightmapcolor4f_bufferoffset = 0;
8046 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8047 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8048 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8049 rsurface.modeltexcoordlightmap2f = NULL;
8050 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8051 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8052 rsurface.modelelement3i = (int *)element3i;
8053 rsurface.modelelement3i_indexbuffer = NULL;
8054 rsurface.modelelement3i_bufferoffset = 0;
8055 rsurface.modelelement3s = (unsigned short *)element3s;
8056 rsurface.modelelement3s_indexbuffer = NULL;
8057 rsurface.modelelement3s_bufferoffset = 0;
8058 rsurface.modellightmapoffsets = NULL;
8059 rsurface.modelsurfaces = NULL;
8060 rsurface.batchgeneratedvertex = false;
8061 rsurface.batchfirstvertex = 0;
8062 rsurface.batchnumvertices = 0;
8063 rsurface.batchfirsttriangle = 0;
8064 rsurface.batchnumtriangles = 0;
8065 rsurface.batchvertex3f = NULL;
8066 rsurface.batchvertex3f_vertexbuffer = NULL;
8067 rsurface.batchvertex3f_bufferoffset = 0;
8068 rsurface.batchsvector3f = NULL;
8069 rsurface.batchsvector3f_vertexbuffer = NULL;
8070 rsurface.batchsvector3f_bufferoffset = 0;
8071 rsurface.batchtvector3f = NULL;
8072 rsurface.batchtvector3f_vertexbuffer = NULL;
8073 rsurface.batchtvector3f_bufferoffset = 0;
8074 rsurface.batchnormal3f = NULL;
8075 rsurface.batchnormal3f_vertexbuffer = NULL;
8076 rsurface.batchnormal3f_bufferoffset = 0;
8077 rsurface.batchlightmapcolor4f = NULL;
8078 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8079 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8080 rsurface.batchtexcoordtexture2f = NULL;
8081 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8082 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8083 rsurface.batchtexcoordlightmap2f = NULL;
8084 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8085 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8086 rsurface.batchvertexmesh = NULL;
8087 rsurface.batchvertexmeshbuffer = NULL;
8088 rsurface.batchvertex3fbuffer = NULL;
8089 rsurface.batchelement3i = NULL;
8090 rsurface.batchelement3i_indexbuffer = NULL;
8091 rsurface.batchelement3i_bufferoffset = 0;
8092 rsurface.batchelement3s = NULL;
8093 rsurface.batchelement3s_indexbuffer = NULL;
8094 rsurface.batchelement3s_bufferoffset = 0;
8095 rsurface.passcolor4f = NULL;
8096 rsurface.passcolor4f_vertexbuffer = NULL;
8097 rsurface.passcolor4f_bufferoffset = 0;
8099 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8101 if ((wantnormals || wanttangents) && !normal3f)
8103 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8104 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8106 if (wanttangents && !svector3f)
8108 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8109 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8110 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8115 float RSurf_FogPoint(const float *v)
8117 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8118 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8119 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8120 float FogHeightFade = r_refdef.fogheightfade;
8122 unsigned int fogmasktableindex;
8123 if (r_refdef.fogplaneviewabove)
8124 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8126 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8127 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8128 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8131 float RSurf_FogVertex(const float *v)
8133 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8134 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8135 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8136 float FogHeightFade = rsurface.fogheightfade;
8138 unsigned int fogmasktableindex;
8139 if (r_refdef.fogplaneviewabove)
8140 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8142 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8143 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8144 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8147 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8150 for (i = 0;i < numelements;i++)
8151 outelement3i[i] = inelement3i[i] + adjust;
8154 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8155 extern cvar_t gl_vbo;
8156 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8164 int surfacefirsttriangle;
8165 int surfacenumtriangles;
8166 int surfacefirstvertex;
8167 int surfaceendvertex;
8168 int surfacenumvertices;
8169 int batchnumvertices;
8170 int batchnumtriangles;
8174 qboolean dynamicvertex;
8178 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8180 q3shaderinfo_deform_t *deform;
8181 const msurface_t *surface, *firstsurface;
8182 r_vertexmesh_t *vertexmesh;
8183 if (!texturenumsurfaces)
8185 // find vertex range of this surface batch
8187 firstsurface = texturesurfacelist[0];
8188 firsttriangle = firstsurface->num_firsttriangle;
8189 batchnumvertices = 0;
8190 batchnumtriangles = 0;
8191 firstvertex = endvertex = firstsurface->num_firstvertex;
8192 for (i = 0;i < texturenumsurfaces;i++)
8194 surface = texturesurfacelist[i];
8195 if (surface != firstsurface + i)
8197 surfacefirstvertex = surface->num_firstvertex;
8198 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8199 surfacenumvertices = surface->num_vertices;
8200 surfacenumtriangles = surface->num_triangles;
8201 if (firstvertex > surfacefirstvertex)
8202 firstvertex = surfacefirstvertex;
8203 if (endvertex < surfaceendvertex)
8204 endvertex = surfaceendvertex;
8205 batchnumvertices += surfacenumvertices;
8206 batchnumtriangles += surfacenumtriangles;
8209 // we now know the vertex range used, and if there are any gaps in it
8210 rsurface.batchfirstvertex = firstvertex;
8211 rsurface.batchnumvertices = endvertex - firstvertex;
8212 rsurface.batchfirsttriangle = firsttriangle;
8213 rsurface.batchnumtriangles = batchnumtriangles;
8215 // this variable holds flags for which properties have been updated that
8216 // may require regenerating vertexmesh array...
8219 // check if any dynamic vertex processing must occur
8220 dynamicvertex = false;
8222 // if there is a chance of animated vertex colors, it's a dynamic batch
8223 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8225 dynamicvertex = true;
8226 batchneed |= BATCHNEED_NOGAPS;
8227 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8230 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8232 switch (deform->deform)
8235 case Q3DEFORM_PROJECTIONSHADOW:
8236 case Q3DEFORM_TEXT0:
8237 case Q3DEFORM_TEXT1:
8238 case Q3DEFORM_TEXT2:
8239 case Q3DEFORM_TEXT3:
8240 case Q3DEFORM_TEXT4:
8241 case Q3DEFORM_TEXT5:
8242 case Q3DEFORM_TEXT6:
8243 case Q3DEFORM_TEXT7:
8246 case Q3DEFORM_AUTOSPRITE:
8247 dynamicvertex = true;
8248 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8249 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8251 case Q3DEFORM_AUTOSPRITE2:
8252 dynamicvertex = true;
8253 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8254 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8256 case Q3DEFORM_NORMAL:
8257 dynamicvertex = true;
8258 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8259 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8262 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8263 break; // if wavefunc is a nop, ignore this transform
8264 dynamicvertex = true;
8265 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8266 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8268 case Q3DEFORM_BULGE:
8269 dynamicvertex = true;
8270 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8271 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8274 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8275 break; // if wavefunc is a nop, ignore this transform
8276 dynamicvertex = true;
8277 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8278 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8282 switch(rsurface.texture->tcgen.tcgen)
8285 case Q3TCGEN_TEXTURE:
8287 case Q3TCGEN_LIGHTMAP:
8288 dynamicvertex = true;
8289 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8290 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8292 case Q3TCGEN_VECTOR:
8293 dynamicvertex = true;
8294 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8295 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8297 case Q3TCGEN_ENVIRONMENT:
8298 dynamicvertex = true;
8299 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8300 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8303 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8305 dynamicvertex = true;
8306 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8307 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8310 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8312 dynamicvertex = true;
8313 batchneed |= BATCHNEED_NOGAPS;
8314 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8317 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8319 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8320 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8321 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8322 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8323 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8324 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8325 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8328 // when the model data has no vertex buffer (dynamic mesh), we need to
8330 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8331 batchneed |= BATCHNEED_NOGAPS;
8333 // if needsupdate, we have to do a dynamic vertex batch for sure
8334 if (needsupdate & batchneed)
8335 dynamicvertex = true;
8337 // see if we need to build vertexmesh from arrays
8338 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8339 dynamicvertex = true;
8341 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8342 // also some drivers strongly dislike firstvertex
8343 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8344 dynamicvertex = true;
8346 rsurface.batchvertex3f = rsurface.modelvertex3f;
8347 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8348 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8349 rsurface.batchsvector3f = rsurface.modelsvector3f;
8350 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8351 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8352 rsurface.batchtvector3f = rsurface.modeltvector3f;
8353 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8354 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8355 rsurface.batchnormal3f = rsurface.modelnormal3f;
8356 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8357 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8358 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8359 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8360 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8361 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8362 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8363 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8364 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8365 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8366 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8367 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8368 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8369 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8370 rsurface.batchelement3i = rsurface.modelelement3i;
8371 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8372 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8373 rsurface.batchelement3s = rsurface.modelelement3s;
8374 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8375 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8377 // if any dynamic vertex processing has to occur in software, we copy the
8378 // entire surface list together before processing to rebase the vertices
8379 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8381 // if any gaps exist and we do not have a static vertex buffer, we have to
8382 // copy the surface list together to avoid wasting upload bandwidth on the
8383 // vertices in the gaps.
8385 // if gaps exist and we have a static vertex buffer, we still have to
8386 // combine the index buffer ranges into one dynamic index buffer.
8388 // in all cases we end up with data that can be drawn in one call.
8392 // static vertex data, just set pointers...
8393 rsurface.batchgeneratedvertex = false;
8394 // if there are gaps, we want to build a combined index buffer,
8395 // otherwise use the original static buffer with an appropriate offset
8398 // build a new triangle elements array for this batch
8399 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8400 rsurface.batchfirsttriangle = 0;
8402 for (i = 0;i < texturenumsurfaces;i++)
8404 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8405 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8406 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8407 numtriangles += surfacenumtriangles;
8409 rsurface.batchelement3i_indexbuffer = NULL;
8410 rsurface.batchelement3i_bufferoffset = 0;
8411 rsurface.batchelement3s = NULL;
8412 rsurface.batchelement3s_indexbuffer = NULL;
8413 rsurface.batchelement3s_bufferoffset = 0;
8414 if (endvertex <= 65536)
8416 // make a 16bit (unsigned short) index array if possible
8417 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8418 for (i = 0;i < numtriangles*3;i++)
8419 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8425 // something needs software processing, do it for real...
8426 // we only directly handle separate array data in this case and then
8427 // generate interleaved data if needed...
8428 rsurface.batchgeneratedvertex = true;
8430 // now copy the vertex data into a combined array and make an index array
8431 // (this is what Quake3 does all the time)
8432 //if (gaps || rsurface.batchfirstvertex)
8434 rsurface.batchvertex3fbuffer = NULL;
8435 rsurface.batchvertexmesh = NULL;
8436 rsurface.batchvertexmeshbuffer = NULL;
8437 rsurface.batchvertex3f = NULL;
8438 rsurface.batchvertex3f_vertexbuffer = NULL;
8439 rsurface.batchvertex3f_bufferoffset = 0;
8440 rsurface.batchsvector3f = NULL;
8441 rsurface.batchsvector3f_vertexbuffer = NULL;
8442 rsurface.batchsvector3f_bufferoffset = 0;
8443 rsurface.batchtvector3f = NULL;
8444 rsurface.batchtvector3f_vertexbuffer = NULL;
8445 rsurface.batchtvector3f_bufferoffset = 0;
8446 rsurface.batchnormal3f = NULL;
8447 rsurface.batchnormal3f_vertexbuffer = NULL;
8448 rsurface.batchnormal3f_bufferoffset = 0;
8449 rsurface.batchlightmapcolor4f = NULL;
8450 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8451 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8452 rsurface.batchtexcoordtexture2f = NULL;
8453 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8454 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8455 rsurface.batchtexcoordlightmap2f = NULL;
8456 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8457 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8458 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8459 rsurface.batchelement3i_indexbuffer = NULL;
8460 rsurface.batchelement3i_bufferoffset = 0;
8461 rsurface.batchelement3s = NULL;
8462 rsurface.batchelement3s_indexbuffer = NULL;
8463 rsurface.batchelement3s_bufferoffset = 0;
8464 // we'll only be setting up certain arrays as needed
8465 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8466 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8467 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8468 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8469 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8470 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8471 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8473 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8474 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8476 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8477 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8478 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8479 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8480 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8481 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8484 for (i = 0;i < texturenumsurfaces;i++)
8486 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8487 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8488 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8489 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8490 // copy only the data requested
8491 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8492 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8493 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8495 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8496 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8497 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8498 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8499 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8501 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8502 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8504 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8505 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8506 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8507 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8508 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8509 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8511 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8512 numvertices += surfacenumvertices;
8513 numtriangles += surfacenumtriangles;
8516 // generate a 16bit index array as well if possible
8517 // (in general, dynamic batches fit)
8518 if (numvertices <= 65536)
8520 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8521 for (i = 0;i < numtriangles*3;i++)
8522 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8525 // since we've copied everything, the batch now starts at 0
8526 rsurface.batchfirstvertex = 0;
8527 rsurface.batchnumvertices = batchnumvertices;
8528 rsurface.batchfirsttriangle = 0;
8529 rsurface.batchnumtriangles = batchnumtriangles;
8532 // q1bsp surfaces rendered in vertex color mode have to have colors
8533 // calculated based on lightstyles
8534 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8536 // generate color arrays for the surfaces in this list
8541 const unsigned char *lm;
8542 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8543 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8544 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8546 for (i = 0;i < texturenumsurfaces;i++)
8548 surface = texturesurfacelist[i];
8549 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8550 surfacenumvertices = surface->num_vertices;
8551 if (surface->lightmapinfo->samples)
8553 for (j = 0;j < surfacenumvertices;j++)
8555 lm = surface->lightmapinfo->samples + offsets[j];
8556 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8557 VectorScale(lm, scale, c);
8558 if (surface->lightmapinfo->styles[1] != 255)
8560 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8562 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8563 VectorMA(c, scale, lm, c);
8564 if (surface->lightmapinfo->styles[2] != 255)
8567 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8568 VectorMA(c, scale, lm, c);
8569 if (surface->lightmapinfo->styles[3] != 255)
8572 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8573 VectorMA(c, scale, lm, c);
8580 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);
8586 for (j = 0;j < surfacenumvertices;j++)
8588 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8595 // if vertices are deformed (sprite flares and things in maps, possibly
8596 // water waves, bulges and other deformations), modify the copied vertices
8598 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8600 switch (deform->deform)
8603 case Q3DEFORM_PROJECTIONSHADOW:
8604 case Q3DEFORM_TEXT0:
8605 case Q3DEFORM_TEXT1:
8606 case Q3DEFORM_TEXT2:
8607 case Q3DEFORM_TEXT3:
8608 case Q3DEFORM_TEXT4:
8609 case Q3DEFORM_TEXT5:
8610 case Q3DEFORM_TEXT6:
8611 case Q3DEFORM_TEXT7:
8614 case Q3DEFORM_AUTOSPRITE:
8615 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8616 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8617 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8618 VectorNormalize(newforward);
8619 VectorNormalize(newright);
8620 VectorNormalize(newup);
8621 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8622 // rsurface.batchvertex3f_vertexbuffer = NULL;
8623 // rsurface.batchvertex3f_bufferoffset = 0;
8624 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8625 // rsurface.batchsvector3f_vertexbuffer = NULL;
8626 // rsurface.batchsvector3f_bufferoffset = 0;
8627 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8628 // rsurface.batchtvector3f_vertexbuffer = NULL;
8629 // rsurface.batchtvector3f_bufferoffset = 0;
8630 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8631 // rsurface.batchnormal3f_vertexbuffer = NULL;
8632 // rsurface.batchnormal3f_bufferoffset = 0;
8633 // a single autosprite surface can contain multiple sprites...
8634 for (j = 0;j < batchnumvertices - 3;j += 4)
8636 VectorClear(center);
8637 for (i = 0;i < 4;i++)
8638 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8639 VectorScale(center, 0.25f, center);
8640 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8641 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8642 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8643 for (i = 0;i < 4;i++)
8645 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8646 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8649 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8650 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8651 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
8653 case Q3DEFORM_AUTOSPRITE2:
8654 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8655 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8656 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8657 VectorNormalize(newforward);
8658 VectorNormalize(newright);
8659 VectorNormalize(newup);
8660 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8661 // rsurface.batchvertex3f_vertexbuffer = NULL;
8662 // rsurface.batchvertex3f_bufferoffset = 0;
8664 const float *v1, *v2;
8674 memset(shortest, 0, sizeof(shortest));
8675 // a single autosprite surface can contain multiple sprites...
8676 for (j = 0;j < batchnumvertices - 3;j += 4)
8678 VectorClear(center);
8679 for (i = 0;i < 4;i++)
8680 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8681 VectorScale(center, 0.25f, center);
8682 // find the two shortest edges, then use them to define the
8683 // axis vectors for rotating around the central axis
8684 for (i = 0;i < 6;i++)
8686 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8687 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8688 l = VectorDistance2(v1, v2);
8689 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8691 l += (1.0f / 1024.0f);
8692 if (shortest[0].length2 > l || i == 0)
8694 shortest[1] = shortest[0];
8695 shortest[0].length2 = l;
8696 shortest[0].v1 = v1;
8697 shortest[0].v2 = v2;
8699 else if (shortest[1].length2 > l || i == 1)
8701 shortest[1].length2 = l;
8702 shortest[1].v1 = v1;
8703 shortest[1].v2 = v2;
8706 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8707 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8708 // this calculates the right vector from the shortest edge
8709 // and the up vector from the edge midpoints
8710 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8711 VectorNormalize(right);
8712 VectorSubtract(end, start, up);
8713 VectorNormalize(up);
8714 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8715 VectorSubtract(rsurface.localvieworigin, center, forward);
8716 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8717 VectorNegate(forward, forward);
8718 VectorReflect(forward, 0, up, forward);
8719 VectorNormalize(forward);
8720 CrossProduct(up, forward, newright);
8721 VectorNormalize(newright);
8722 // rotate the quad around the up axis vector, this is made
8723 // especially easy by the fact we know the quad is flat,
8724 // so we only have to subtract the center position and
8725 // measure distance along the right vector, and then
8726 // multiply that by the newright vector and add back the
8728 // we also need to subtract the old position to undo the
8729 // displacement from the center, which we do with a
8730 // DotProduct, the subtraction/addition of center is also
8731 // optimized into DotProducts here
8732 l = DotProduct(right, center);
8733 for (i = 0;i < 4;i++)
8735 v1 = rsurface.batchvertex3f + 3*(j+i);
8736 f = DotProduct(right, v1) - l;
8737 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8741 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8743 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8744 // rsurface.batchnormal3f_vertexbuffer = NULL;
8745 // rsurface.batchnormal3f_bufferoffset = 0;
8746 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8748 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8750 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8751 // rsurface.batchsvector3f_vertexbuffer = NULL;
8752 // rsurface.batchsvector3f_bufferoffset = 0;
8753 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8754 // rsurface.batchtvector3f_vertexbuffer = NULL;
8755 // rsurface.batchtvector3f_bufferoffset = 0;
8756 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);
8759 case Q3DEFORM_NORMAL:
8760 // deform the normals to make reflections wavey
8761 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8762 rsurface.batchnormal3f_vertexbuffer = NULL;
8763 rsurface.batchnormal3f_bufferoffset = 0;
8764 for (j = 0;j < batchnumvertices;j++)
8767 float *normal = rsurface.batchnormal3f + 3*j;
8768 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8769 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8770 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]);
8771 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]);
8772 VectorNormalize(normal);
8774 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8776 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8777 // rsurface.batchsvector3f_vertexbuffer = NULL;
8778 // rsurface.batchsvector3f_bufferoffset = 0;
8779 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8780 // rsurface.batchtvector3f_vertexbuffer = NULL;
8781 // rsurface.batchtvector3f_bufferoffset = 0;
8782 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);
8786 // deform vertex array to make wavey water and flags and such
8787 waveparms[0] = deform->waveparms[0];
8788 waveparms[1] = deform->waveparms[1];
8789 waveparms[2] = deform->waveparms[2];
8790 waveparms[3] = deform->waveparms[3];
8791 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8792 break; // if wavefunc is a nop, don't make a dynamic vertex array
8793 // this is how a divisor of vertex influence on deformation
8794 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8795 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8796 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8797 // rsurface.batchvertex3f_vertexbuffer = NULL;
8798 // rsurface.batchvertex3f_bufferoffset = 0;
8799 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8800 // rsurface.batchnormal3f_vertexbuffer = NULL;
8801 // rsurface.batchnormal3f_bufferoffset = 0;
8802 for (j = 0;j < batchnumvertices;j++)
8804 // if the wavefunc depends on time, evaluate it per-vertex
8807 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8808 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8810 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8812 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8813 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8814 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8816 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8817 // rsurface.batchsvector3f_vertexbuffer = NULL;
8818 // rsurface.batchsvector3f_bufferoffset = 0;
8819 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8820 // rsurface.batchtvector3f_vertexbuffer = NULL;
8821 // rsurface.batchtvector3f_bufferoffset = 0;
8822 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);
8825 case Q3DEFORM_BULGE:
8826 // deform vertex array to make the surface have moving bulges
8827 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8828 // rsurface.batchvertex3f_vertexbuffer = NULL;
8829 // rsurface.batchvertex3f_bufferoffset = 0;
8830 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8831 // rsurface.batchnormal3f_vertexbuffer = NULL;
8832 // rsurface.batchnormal3f_bufferoffset = 0;
8833 for (j = 0;j < batchnumvertices;j++)
8835 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8836 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8838 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8839 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8840 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8842 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8843 // rsurface.batchsvector3f_vertexbuffer = NULL;
8844 // rsurface.batchsvector3f_bufferoffset = 0;
8845 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8846 // rsurface.batchtvector3f_vertexbuffer = NULL;
8847 // rsurface.batchtvector3f_bufferoffset = 0;
8848 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);
8852 // deform vertex array
8853 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8854 break; // if wavefunc is a nop, don't make a dynamic vertex array
8855 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8856 VectorScale(deform->parms, scale, waveparms);
8857 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8858 // rsurface.batchvertex3f_vertexbuffer = NULL;
8859 // rsurface.batchvertex3f_bufferoffset = 0;
8860 for (j = 0;j < batchnumvertices;j++)
8861 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8866 // generate texcoords based on the chosen texcoord source
8867 switch(rsurface.texture->tcgen.tcgen)
8870 case Q3TCGEN_TEXTURE:
8872 case Q3TCGEN_LIGHTMAP:
8873 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8874 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8875 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8876 if (rsurface.batchtexcoordlightmap2f)
8877 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8879 case Q3TCGEN_VECTOR:
8880 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8881 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8882 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8883 for (j = 0;j < batchnumvertices;j++)
8885 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8886 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8889 case Q3TCGEN_ENVIRONMENT:
8890 // make environment reflections using a spheremap
8891 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8892 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8893 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8894 for (j = 0;j < batchnumvertices;j++)
8896 // identical to Q3A's method, but executed in worldspace so
8897 // carried models can be shiny too
8899 float viewer[3], d, reflected[3], worldreflected[3];
8901 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8902 // VectorNormalize(viewer);
8904 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8906 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8907 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8908 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8909 // note: this is proportinal to viewer, so we can normalize later
8911 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8912 VectorNormalize(worldreflected);
8914 // note: this sphere map only uses world x and z!
8915 // so positive and negative y will LOOK THE SAME.
8916 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8917 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8921 // the only tcmod that needs software vertex processing is turbulent, so
8922 // check for it here and apply the changes if needed
8923 // and we only support that as the first one
8924 // (handling a mixture of turbulent and other tcmods would be problematic
8925 // without punting it entirely to a software path)
8926 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8928 amplitude = rsurface.texture->tcmods[0].parms[1];
8929 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8930 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8931 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8932 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8933 for (j = 0;j < batchnumvertices;j++)
8935 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);
8936 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8940 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8942 // convert the modified arrays to vertex structs
8943 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8944 // rsurface.batchvertexmeshbuffer = NULL;
8945 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8946 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8947 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8948 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8949 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8950 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
8951 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
8953 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8955 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
8956 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
8959 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
8960 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8961 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
8962 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
8963 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8964 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
8965 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
8966 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8967 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
8971 void RSurf_DrawBatch(void)
8973 // sometimes a zero triangle surface (usually a degenerate patch) makes it
8974 // through the pipeline, killing it earlier in the pipeline would have
8975 // per-surface overhead rather than per-batch overhead, so it's best to
8976 // reject it here, before it hits glDraw.
8977 if (rsurface.batchnumtriangles == 0)
8980 // batch debugging code
8981 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
8987 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
8988 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
8991 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
8993 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
8995 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
8996 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);
9003 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);
9006 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9008 // pick the closest matching water plane
9009 int planeindex, vertexindex, bestplaneindex = -1;
9013 r_waterstate_waterplane_t *p;
9014 qboolean prepared = false;
9016 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9018 if(p->camera_entity != rsurface.texture->camera_entity)
9023 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9025 if(rsurface.batchnumvertices == 0)
9028 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9030 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9031 d += fabs(PlaneDiff(vert, &p->plane));
9033 if (bestd > d || bestplaneindex < 0)
9036 bestplaneindex = planeindex;
9039 return bestplaneindex;
9040 // NOTE: this MAY return a totally unrelated water plane; we can ignore
9041 // this situation though, as it might be better to render single larger
9042 // batches with useless stuff (backface culled for example) than to
9043 // render multiple smaller batches
9046 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9049 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9050 rsurface.passcolor4f_vertexbuffer = 0;
9051 rsurface.passcolor4f_bufferoffset = 0;
9052 for (i = 0;i < rsurface.batchnumvertices;i++)
9053 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9056 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9063 if (rsurface.passcolor4f)
9065 // generate color arrays
9066 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9067 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9068 rsurface.passcolor4f_vertexbuffer = 0;
9069 rsurface.passcolor4f_bufferoffset = 0;
9070 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)
9072 f = RSurf_FogVertex(v);
9081 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9082 rsurface.passcolor4f_vertexbuffer = 0;
9083 rsurface.passcolor4f_bufferoffset = 0;
9084 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9086 f = RSurf_FogVertex(v);
9095 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9102 if (!rsurface.passcolor4f)
9104 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9105 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9106 rsurface.passcolor4f_vertexbuffer = 0;
9107 rsurface.passcolor4f_bufferoffset = 0;
9108 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)
9110 f = RSurf_FogVertex(v);
9111 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9112 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9113 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9118 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9123 if (!rsurface.passcolor4f)
9125 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9126 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9127 rsurface.passcolor4f_vertexbuffer = 0;
9128 rsurface.passcolor4f_bufferoffset = 0;
9129 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9138 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9143 if (!rsurface.passcolor4f)
9145 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9146 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9147 rsurface.passcolor4f_vertexbuffer = 0;
9148 rsurface.passcolor4f_bufferoffset = 0;
9149 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9151 c2[0] = c[0] + r_refdef.scene.ambient;
9152 c2[1] = c[1] + r_refdef.scene.ambient;
9153 c2[2] = c[2] + r_refdef.scene.ambient;
9158 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9161 rsurface.passcolor4f = NULL;
9162 rsurface.passcolor4f_vertexbuffer = 0;
9163 rsurface.passcolor4f_bufferoffset = 0;
9164 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9165 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9166 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9167 GL_Color(r, g, b, a);
9168 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9172 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9174 // TODO: optimize applyfog && applycolor case
9175 // just apply fog if necessary, and tint the fog color array if necessary
9176 rsurface.passcolor4f = NULL;
9177 rsurface.passcolor4f_vertexbuffer = 0;
9178 rsurface.passcolor4f_bufferoffset = 0;
9179 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9180 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9181 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9182 GL_Color(r, g, b, a);
9186 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9189 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9190 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9191 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9192 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9193 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9194 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9195 GL_Color(r, g, b, a);
9199 static void RSurf_DrawBatch_GL11_ClampColor(void)
9204 if (!rsurface.passcolor4f)
9206 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9208 c2[0] = bound(0.0f, c1[0], 1.0f);
9209 c2[1] = bound(0.0f, c1[1], 1.0f);
9210 c2[2] = bound(0.0f, c1[2], 1.0f);
9211 c2[3] = bound(0.0f, c1[3], 1.0f);
9215 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9225 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9226 rsurface.passcolor4f_vertexbuffer = 0;
9227 rsurface.passcolor4f_bufferoffset = 0;
9228 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)
9230 f = -DotProduct(r_refdef.view.forward, n);
9232 f = f * 0.85 + 0.15; // work around so stuff won't get black
9233 f *= r_refdef.lightmapintensity;
9234 Vector4Set(c, f, f, f, 1);
9238 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9240 RSurf_DrawBatch_GL11_ApplyFakeLight();
9241 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9242 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9243 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9244 GL_Color(r, g, b, a);
9248 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9256 vec3_t ambientcolor;
9257 vec3_t diffusecolor;
9261 VectorCopy(rsurface.modellight_lightdir, lightdir);
9262 f = 0.5f * r_refdef.lightmapintensity;
9263 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9264 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9265 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9266 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9267 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9268 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9270 if (VectorLength2(diffusecolor) > 0)
9272 // q3-style directional shading
9273 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9274 rsurface.passcolor4f_vertexbuffer = 0;
9275 rsurface.passcolor4f_bufferoffset = 0;
9276 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)
9278 if ((f = DotProduct(n, lightdir)) > 0)
9279 VectorMA(ambientcolor, f, diffusecolor, c);
9281 VectorCopy(ambientcolor, c);
9288 *applycolor = false;
9292 *r = ambientcolor[0];
9293 *g = ambientcolor[1];
9294 *b = ambientcolor[2];
9295 rsurface.passcolor4f = NULL;
9296 rsurface.passcolor4f_vertexbuffer = 0;
9297 rsurface.passcolor4f_bufferoffset = 0;
9301 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9303 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9304 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9305 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9306 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9307 GL_Color(r, g, b, a);
9311 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9317 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9319 f = 1 - RSurf_FogVertex(v);
9327 void RSurf_SetupDepthAndCulling(void)
9329 // submodels are biased to avoid z-fighting with world surfaces that they
9330 // may be exactly overlapping (avoids z-fighting artifacts on certain
9331 // doors and things in Quake maps)
9332 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9333 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9334 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9335 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9338 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9340 // transparent sky would be ridiculous
9341 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9343 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9344 skyrenderlater = true;
9345 RSurf_SetupDepthAndCulling();
9347 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9348 // skymasking on them, and Quake3 never did sky masking (unlike
9349 // software Quake and software Quake2), so disable the sky masking
9350 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9351 // and skymasking also looks very bad when noclipping outside the
9352 // level, so don't use it then either.
9353 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9355 R_Mesh_ResetTextureState();
9356 if (skyrendermasked)
9358 R_SetupShader_DepthOrShadow();
9359 // depth-only (masking)
9360 GL_ColorMask(0,0,0,0);
9361 // just to make sure that braindead drivers don't draw
9362 // anything despite that colormask...
9363 GL_BlendFunc(GL_ZERO, GL_ONE);
9364 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9365 if (rsurface.batchvertex3fbuffer)
9366 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9368 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9372 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9374 GL_BlendFunc(GL_ONE, GL_ZERO);
9375 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9376 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9377 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9380 if (skyrendermasked)
9381 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9383 R_Mesh_ResetTextureState();
9384 GL_Color(1, 1, 1, 1);
9387 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9388 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9389 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9391 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9395 // render screenspace normalmap to texture
9397 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9402 // bind lightmap texture
9404 // water/refraction/reflection/camera surfaces have to be handled specially
9405 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9407 int start, end, startplaneindex;
9408 for (start = 0;start < texturenumsurfaces;start = end)
9410 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9411 if(startplaneindex < 0)
9413 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9414 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9418 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9420 // now that we have a batch using the same planeindex, render it
9421 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9423 // render water or distortion background
9425 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));
9427 // blend surface on top
9428 GL_DepthMask(false);
9429 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9432 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9434 // render surface with reflection texture as input
9435 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9436 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));
9443 // render surface batch normally
9444 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9445 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9449 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9451 // OpenGL 1.3 path - anything not completely ancient
9452 qboolean applycolor;
9455 const texturelayer_t *layer;
9456 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);
9457 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9459 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9462 int layertexrgbscale;
9463 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9465 if (layerindex == 0)
9469 GL_AlphaTest(false);
9470 GL_DepthFunc(GL_EQUAL);
9473 GL_DepthMask(layer->depthmask && writedepth);
9474 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9475 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9477 layertexrgbscale = 4;
9478 VectorScale(layer->color, 0.25f, layercolor);
9480 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9482 layertexrgbscale = 2;
9483 VectorScale(layer->color, 0.5f, layercolor);
9487 layertexrgbscale = 1;
9488 VectorScale(layer->color, 1.0f, layercolor);
9490 layercolor[3] = layer->color[3];
9491 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9492 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9493 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9494 switch (layer->type)
9496 case TEXTURELAYERTYPE_LITTEXTURE:
9497 // single-pass lightmapped texture with 2x rgbscale
9498 R_Mesh_TexBind(0, r_texture_white);
9499 R_Mesh_TexMatrix(0, NULL);
9500 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9501 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9502 R_Mesh_TexBind(1, layer->texture);
9503 R_Mesh_TexMatrix(1, &layer->texmatrix);
9504 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9505 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9506 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9507 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9508 else if (FAKELIGHT_ENABLED)
9509 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9510 else if (rsurface.uselightmaptexture)
9511 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9513 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9515 case TEXTURELAYERTYPE_TEXTURE:
9516 // singletexture unlit texture with transparency support
9517 R_Mesh_TexBind(0, layer->texture);
9518 R_Mesh_TexMatrix(0, &layer->texmatrix);
9519 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9520 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9521 R_Mesh_TexBind(1, 0);
9522 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9523 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9525 case TEXTURELAYERTYPE_FOG:
9526 // singletexture fogging
9529 R_Mesh_TexBind(0, layer->texture);
9530 R_Mesh_TexMatrix(0, &layer->texmatrix);
9531 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9532 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9536 R_Mesh_TexBind(0, 0);
9537 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9539 R_Mesh_TexBind(1, 0);
9540 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9541 // generate a color array for the fog pass
9542 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9543 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9547 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9550 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9552 GL_DepthFunc(GL_LEQUAL);
9553 GL_AlphaTest(false);
9557 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9559 // OpenGL 1.1 - crusty old voodoo path
9562 const texturelayer_t *layer;
9563 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);
9564 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9566 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9568 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9570 if (layerindex == 0)
9574 GL_AlphaTest(false);
9575 GL_DepthFunc(GL_EQUAL);
9578 GL_DepthMask(layer->depthmask && writedepth);
9579 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9580 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9581 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9582 switch (layer->type)
9584 case TEXTURELAYERTYPE_LITTEXTURE:
9585 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9587 // two-pass lit texture with 2x rgbscale
9588 // first the lightmap pass
9589 R_Mesh_TexBind(0, r_texture_white);
9590 R_Mesh_TexMatrix(0, NULL);
9591 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9592 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9593 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9594 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9595 else if (FAKELIGHT_ENABLED)
9596 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9597 else if (rsurface.uselightmaptexture)
9598 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9600 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9601 // then apply the texture to it
9602 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9603 R_Mesh_TexBind(0, layer->texture);
9604 R_Mesh_TexMatrix(0, &layer->texmatrix);
9605 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9606 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9607 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);
9611 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9612 R_Mesh_TexBind(0, layer->texture);
9613 R_Mesh_TexMatrix(0, &layer->texmatrix);
9614 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9615 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9616 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9617 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);
9619 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);
9622 case TEXTURELAYERTYPE_TEXTURE:
9623 // singletexture unlit texture with transparency support
9624 R_Mesh_TexBind(0, layer->texture);
9625 R_Mesh_TexMatrix(0, &layer->texmatrix);
9626 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9627 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9628 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);
9630 case TEXTURELAYERTYPE_FOG:
9631 // singletexture fogging
9634 R_Mesh_TexBind(0, layer->texture);
9635 R_Mesh_TexMatrix(0, &layer->texmatrix);
9636 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9637 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9641 R_Mesh_TexBind(0, 0);
9642 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9644 // generate a color array for the fog pass
9645 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9646 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9650 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9653 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9655 GL_DepthFunc(GL_LEQUAL);
9656 GL_AlphaTest(false);
9660 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9664 r_vertexgeneric_t *batchvertex;
9667 // R_Mesh_ResetTextureState();
9668 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9670 if(rsurface.texture && rsurface.texture->currentskinframe)
9672 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9673 c[3] *= rsurface.texture->currentalpha;
9683 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9685 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9686 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9687 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9690 // brighten it up (as texture value 127 means "unlit")
9691 c[0] *= 2 * r_refdef.view.colorscale;
9692 c[1] *= 2 * r_refdef.view.colorscale;
9693 c[2] *= 2 * r_refdef.view.colorscale;
9695 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9696 c[3] *= r_wateralpha.value;
9698 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9700 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9701 GL_DepthMask(false);
9703 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9705 GL_BlendFunc(GL_ONE, GL_ONE);
9706 GL_DepthMask(false);
9708 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9710 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9711 GL_DepthMask(false);
9713 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9715 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9716 GL_DepthMask(false);
9720 GL_BlendFunc(GL_ONE, GL_ZERO);
9721 GL_DepthMask(writedepth);
9724 if (r_showsurfaces.integer == 3)
9726 rsurface.passcolor4f = NULL;
9728 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9730 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9732 rsurface.passcolor4f = NULL;
9733 rsurface.passcolor4f_vertexbuffer = 0;
9734 rsurface.passcolor4f_bufferoffset = 0;
9736 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9738 qboolean applycolor = true;
9741 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9743 r_refdef.lightmapintensity = 1;
9744 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9745 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9747 else if (FAKELIGHT_ENABLED)
9749 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9751 r_refdef.lightmapintensity = r_fakelight_intensity.value;
9752 RSurf_DrawBatch_GL11_ApplyFakeLight();
9753 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9757 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9759 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9760 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9761 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9764 if(!rsurface.passcolor4f)
9765 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9767 RSurf_DrawBatch_GL11_ApplyAmbient();
9768 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9769 if(r_refdef.fogenabled)
9770 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9771 RSurf_DrawBatch_GL11_ClampColor();
9773 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9774 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9777 else if (!r_refdef.view.showdebug)
9779 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9780 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9781 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9783 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9784 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9786 R_Mesh_PrepareVertices_Generic_Unlock();
9789 else if (r_showsurfaces.integer == 4)
9791 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9792 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9793 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9795 unsigned char c = (vi << 3) * (1.0f / 256.0f);
9796 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9797 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9799 R_Mesh_PrepareVertices_Generic_Unlock();
9802 else if (r_showsurfaces.integer == 2)
9805 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9806 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9807 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9809 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9810 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9811 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9812 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9813 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9814 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9815 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9817 R_Mesh_PrepareVertices_Generic_Unlock();
9818 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9822 int texturesurfaceindex;
9824 const msurface_t *surface;
9825 float surfacecolor4f[4];
9826 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9827 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9829 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9831 surface = texturesurfacelist[texturesurfaceindex];
9832 k = (int)(((size_t)surface) / sizeof(msurface_t));
9833 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9834 for (j = 0;j < surface->num_vertices;j++)
9836 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9837 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9841 R_Mesh_PrepareVertices_Generic_Unlock();
9846 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9849 RSurf_SetupDepthAndCulling();
9850 if (r_showsurfaces.integer)
9852 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9855 switch (vid.renderpath)
9857 case RENDERPATH_GL20:
9858 case RENDERPATH_D3D9:
9859 case RENDERPATH_D3D10:
9860 case RENDERPATH_D3D11:
9861 case RENDERPATH_SOFT:
9862 case RENDERPATH_GLES2:
9863 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9865 case RENDERPATH_GL13:
9866 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9868 case RENDERPATH_GL11:
9869 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9875 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9878 RSurf_SetupDepthAndCulling();
9879 if (r_showsurfaces.integer)
9881 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9884 switch (vid.renderpath)
9886 case RENDERPATH_GL20:
9887 case RENDERPATH_D3D9:
9888 case RENDERPATH_D3D10:
9889 case RENDERPATH_D3D11:
9890 case RENDERPATH_SOFT:
9891 case RENDERPATH_GLES2:
9892 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9894 case RENDERPATH_GL13:
9895 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9897 case RENDERPATH_GL11:
9898 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9904 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9907 int texturenumsurfaces, endsurface;
9909 const msurface_t *surface;
9910 #define MAXBATCH_TRANSPARENTSURFACES 256
9911 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9913 // if the model is static it doesn't matter what value we give for
9914 // wantnormals and wanttangents, so this logic uses only rules applicable
9915 // to a model, knowing that they are meaningless otherwise
9916 if (ent == r_refdef.scene.worldentity)
9917 RSurf_ActiveWorldEntity();
9918 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9919 RSurf_ActiveModelEntity(ent, false, false, false);
9922 switch (vid.renderpath)
9924 case RENDERPATH_GL20:
9925 case RENDERPATH_D3D9:
9926 case RENDERPATH_D3D10:
9927 case RENDERPATH_D3D11:
9928 case RENDERPATH_SOFT:
9929 case RENDERPATH_GLES2:
9930 RSurf_ActiveModelEntity(ent, true, true, false);
9932 case RENDERPATH_GL13:
9933 case RENDERPATH_GL11:
9934 RSurf_ActiveModelEntity(ent, true, false, false);
9939 if (r_transparentdepthmasking.integer)
9941 qboolean setup = false;
9942 for (i = 0;i < numsurfaces;i = j)
9945 surface = rsurface.modelsurfaces + surfacelist[i];
9946 texture = surface->texture;
9947 rsurface.texture = R_GetCurrentTexture(texture);
9948 rsurface.lightmaptexture = NULL;
9949 rsurface.deluxemaptexture = NULL;
9950 rsurface.uselightmaptexture = false;
9951 // scan ahead until we find a different texture
9952 endsurface = min(i + 1024, numsurfaces);
9953 texturenumsurfaces = 0;
9954 texturesurfacelist[texturenumsurfaces++] = surface;
9955 for (;j < endsurface;j++)
9957 surface = rsurface.modelsurfaces + surfacelist[j];
9958 if (texture != surface->texture)
9960 texturesurfacelist[texturenumsurfaces++] = surface;
9962 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9964 // render the range of surfaces as depth
9968 GL_ColorMask(0,0,0,0);
9971 GL_BlendFunc(GL_ONE, GL_ZERO);
9973 // R_Mesh_ResetTextureState();
9974 R_SetupShader_DepthOrShadow();
9976 RSurf_SetupDepthAndCulling();
9977 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9978 if (rsurface.batchvertex3fbuffer)
9979 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9981 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9985 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9988 for (i = 0;i < numsurfaces;i = j)
9991 surface = rsurface.modelsurfaces + surfacelist[i];
9992 texture = surface->texture;
9993 rsurface.texture = R_GetCurrentTexture(texture);
9994 // scan ahead until we find a different texture
9995 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
9996 texturenumsurfaces = 0;
9997 texturesurfacelist[texturenumsurfaces++] = surface;
9998 if(FAKELIGHT_ENABLED)
10000 rsurface.lightmaptexture = NULL;
10001 rsurface.deluxemaptexture = NULL;
10002 rsurface.uselightmaptexture = false;
10003 for (;j < endsurface;j++)
10005 surface = rsurface.modelsurfaces + surfacelist[j];
10006 if (texture != surface->texture)
10008 texturesurfacelist[texturenumsurfaces++] = surface;
10013 rsurface.lightmaptexture = surface->lightmaptexture;
10014 rsurface.deluxemaptexture = surface->deluxemaptexture;
10015 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10016 for (;j < endsurface;j++)
10018 surface = rsurface.modelsurfaces + surfacelist[j];
10019 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10021 texturesurfacelist[texturenumsurfaces++] = surface;
10024 // render the range of surfaces
10025 if (ent == r_refdef.scene.worldentity)
10026 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10028 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10030 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10033 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10035 // transparent surfaces get pushed off into the transparent queue
10036 int surfacelistindex;
10037 const msurface_t *surface;
10038 vec3_t tempcenter, center;
10039 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10041 surface = texturesurfacelist[surfacelistindex];
10042 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10043 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10044 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10045 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10046 if (queueentity->transparent_offset) // transparent offset
10048 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10049 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10050 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10052 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10056 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10058 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10060 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10062 RSurf_SetupDepthAndCulling();
10063 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10064 if (rsurface.batchvertex3fbuffer)
10065 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10067 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10071 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10073 const entity_render_t *queueentity = r_refdef.scene.worldentity;
10076 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10079 if (!rsurface.texture->currentnumlayers)
10081 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10082 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10084 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10086 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10087 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10088 else if (!rsurface.texture->currentnumlayers)
10090 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10092 // in the deferred case, transparent surfaces were queued during prepass
10093 if (!r_shadow_usingdeferredprepass)
10094 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10098 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10099 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10104 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10107 texture_t *texture;
10108 R_FrameData_SetMark();
10109 // break the surface list down into batches by texture and use of lightmapping
10110 for (i = 0;i < numsurfaces;i = j)
10113 // texture is the base texture pointer, rsurface.texture is the
10114 // current frame/skin the texture is directing us to use (for example
10115 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10116 // use skin 1 instead)
10117 texture = surfacelist[i]->texture;
10118 rsurface.texture = R_GetCurrentTexture(texture);
10119 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10121 // if this texture is not the kind we want, skip ahead to the next one
10122 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10126 if(FAKELIGHT_ENABLED || depthonly || prepass)
10128 rsurface.lightmaptexture = NULL;
10129 rsurface.deluxemaptexture = NULL;
10130 rsurface.uselightmaptexture = false;
10131 // simply scan ahead until we find a different texture or lightmap state
10132 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10137 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10138 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10139 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10140 // simply scan ahead until we find a different texture or lightmap state
10141 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10144 // render the range of surfaces
10145 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10147 R_FrameData_ReturnToMark();
10150 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10154 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10157 if (!rsurface.texture->currentnumlayers)
10159 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10160 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10162 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10164 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10165 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10166 else if (!rsurface.texture->currentnumlayers)
10168 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10170 // in the deferred case, transparent surfaces were queued during prepass
10171 if (!r_shadow_usingdeferredprepass)
10172 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10176 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10177 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10182 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10185 texture_t *texture;
10186 R_FrameData_SetMark();
10187 // break the surface list down into batches by texture and use of lightmapping
10188 for (i = 0;i < numsurfaces;i = j)
10191 // texture is the base texture pointer, rsurface.texture is the
10192 // current frame/skin the texture is directing us to use (for example
10193 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10194 // use skin 1 instead)
10195 texture = surfacelist[i]->texture;
10196 rsurface.texture = R_GetCurrentTexture(texture);
10197 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10199 // if this texture is not the kind we want, skip ahead to the next one
10200 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10204 if(FAKELIGHT_ENABLED || depthonly || prepass)
10206 rsurface.lightmaptexture = NULL;
10207 rsurface.deluxemaptexture = NULL;
10208 rsurface.uselightmaptexture = false;
10209 // simply scan ahead until we find a different texture or lightmap state
10210 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10215 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10216 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10217 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10218 // simply scan ahead until we find a different texture or lightmap state
10219 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10222 // render the range of surfaces
10223 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10225 R_FrameData_ReturnToMark();
10228 float locboxvertex3f[6*4*3] =
10230 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10231 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10232 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10233 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10234 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10235 1,0,0, 0,0,0, 0,1,0, 1,1,0
10238 unsigned short locboxelements[6*2*3] =
10243 12,13,14, 12,14,15,
10244 16,17,18, 16,18,19,
10248 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10251 cl_locnode_t *loc = (cl_locnode_t *)ent;
10253 float vertex3f[6*4*3];
10255 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10256 GL_DepthMask(false);
10257 GL_DepthRange(0, 1);
10258 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10259 GL_DepthTest(true);
10260 GL_CullFace(GL_NONE);
10261 R_EntityMatrix(&identitymatrix);
10263 // R_Mesh_ResetTextureState();
10265 i = surfacelist[0];
10266 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10267 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10268 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10269 surfacelist[0] < 0 ? 0.5f : 0.125f);
10271 if (VectorCompare(loc->mins, loc->maxs))
10273 VectorSet(size, 2, 2, 2);
10274 VectorMA(loc->mins, -0.5f, size, mins);
10278 VectorCopy(loc->mins, mins);
10279 VectorSubtract(loc->maxs, loc->mins, size);
10282 for (i = 0;i < 6*4*3;)
10283 for (j = 0;j < 3;j++, i++)
10284 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10286 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10287 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10288 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10291 void R_DrawLocs(void)
10294 cl_locnode_t *loc, *nearestloc;
10296 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10297 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10299 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10300 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10304 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10306 if (decalsystem->decals)
10307 Mem_Free(decalsystem->decals);
10308 memset(decalsystem, 0, sizeof(*decalsystem));
10311 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)
10314 tridecal_t *decals;
10317 // expand or initialize the system
10318 if (decalsystem->maxdecals <= decalsystem->numdecals)
10320 decalsystem_t old = *decalsystem;
10321 qboolean useshortelements;
10322 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10323 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10324 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)));
10325 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10326 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10327 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10328 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10329 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10330 if (decalsystem->numdecals)
10331 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10333 Mem_Free(old.decals);
10334 for (i = 0;i < decalsystem->maxdecals*3;i++)
10335 decalsystem->element3i[i] = i;
10336 if (useshortelements)
10337 for (i = 0;i < decalsystem->maxdecals*3;i++)
10338 decalsystem->element3s[i] = i;
10341 // grab a decal and search for another free slot for the next one
10342 decals = decalsystem->decals;
10343 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10344 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10346 decalsystem->freedecal = i;
10347 if (decalsystem->numdecals <= i)
10348 decalsystem->numdecals = i + 1;
10350 // initialize the decal
10352 decal->triangleindex = triangleindex;
10353 decal->surfaceindex = surfaceindex;
10354 decal->decalsequence = decalsequence;
10355 decal->color4f[0][0] = c0[0];
10356 decal->color4f[0][1] = c0[1];
10357 decal->color4f[0][2] = c0[2];
10358 decal->color4f[0][3] = 1;
10359 decal->color4f[1][0] = c1[0];
10360 decal->color4f[1][1] = c1[1];
10361 decal->color4f[1][2] = c1[2];
10362 decal->color4f[1][3] = 1;
10363 decal->color4f[2][0] = c2[0];
10364 decal->color4f[2][1] = c2[1];
10365 decal->color4f[2][2] = c2[2];
10366 decal->color4f[2][3] = 1;
10367 decal->vertex3f[0][0] = v0[0];
10368 decal->vertex3f[0][1] = v0[1];
10369 decal->vertex3f[0][2] = v0[2];
10370 decal->vertex3f[1][0] = v1[0];
10371 decal->vertex3f[1][1] = v1[1];
10372 decal->vertex3f[1][2] = v1[2];
10373 decal->vertex3f[2][0] = v2[0];
10374 decal->vertex3f[2][1] = v2[1];
10375 decal->vertex3f[2][2] = v2[2];
10376 decal->texcoord2f[0][0] = t0[0];
10377 decal->texcoord2f[0][1] = t0[1];
10378 decal->texcoord2f[1][0] = t1[0];
10379 decal->texcoord2f[1][1] = t1[1];
10380 decal->texcoord2f[2][0] = t2[0];
10381 decal->texcoord2f[2][1] = t2[1];
10384 extern cvar_t cl_decals_bias;
10385 extern cvar_t cl_decals_models;
10386 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10387 // baseparms, parms, temps
10388 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)
10393 const float *vertex3f;
10394 const float *normal3f;
10396 float points[2][9][3];
10403 e = rsurface.modelelement3i + 3*triangleindex;
10405 vertex3f = rsurface.modelvertex3f;
10406 normal3f = rsurface.modelnormal3f;
10408 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10410 index = 3*e[cornerindex];
10411 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10414 //TriangleNormal(v[0], v[1], v[2], normal);
10415 //if (DotProduct(normal, localnormal) < 0.0f)
10417 // clip by each of the box planes formed from the projection matrix
10418 // if anything survives, we emit the decal
10419 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]);
10422 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]);
10425 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]);
10428 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]);
10431 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]);
10434 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]);
10437 // some part of the triangle survived, so we have to accept it...
10440 // dynamic always uses the original triangle
10442 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10444 index = 3*e[cornerindex];
10445 VectorCopy(vertex3f + index, v[cornerindex]);
10448 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10450 // convert vertex positions to texcoords
10451 Matrix4x4_Transform(projection, v[cornerindex], temp);
10452 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10453 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10454 // calculate distance fade from the projection origin
10455 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10456 f = bound(0.0f, f, 1.0f);
10457 c[cornerindex][0] = r * f;
10458 c[cornerindex][1] = g * f;
10459 c[cornerindex][2] = b * f;
10460 c[cornerindex][3] = 1.0f;
10461 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10464 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);
10466 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10467 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);
10469 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)
10471 matrix4x4_t projection;
10472 decalsystem_t *decalsystem;
10475 const msurface_t *surface;
10476 const msurface_t *surfaces;
10477 const int *surfacelist;
10478 const texture_t *texture;
10480 int numsurfacelist;
10481 int surfacelistindex;
10484 float localorigin[3];
10485 float localnormal[3];
10486 float localmins[3];
10487 float localmaxs[3];
10490 float planes[6][4];
10493 int bih_triangles_count;
10494 int bih_triangles[256];
10495 int bih_surfaces[256];
10497 decalsystem = &ent->decalsystem;
10498 model = ent->model;
10499 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10501 R_DecalSystem_Reset(&ent->decalsystem);
10505 if (!model->brush.data_leafs && !cl_decals_models.integer)
10507 if (decalsystem->model)
10508 R_DecalSystem_Reset(decalsystem);
10512 if (decalsystem->model != model)
10513 R_DecalSystem_Reset(decalsystem);
10514 decalsystem->model = model;
10516 RSurf_ActiveModelEntity(ent, true, false, false);
10518 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10519 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10520 VectorNormalize(localnormal);
10521 localsize = worldsize*rsurface.inversematrixscale;
10522 localmins[0] = localorigin[0] - localsize;
10523 localmins[1] = localorigin[1] - localsize;
10524 localmins[2] = localorigin[2] - localsize;
10525 localmaxs[0] = localorigin[0] + localsize;
10526 localmaxs[1] = localorigin[1] + localsize;
10527 localmaxs[2] = localorigin[2] + localsize;
10529 //VectorCopy(localnormal, planes[4]);
10530 //VectorVectors(planes[4], planes[2], planes[0]);
10531 AnglesFromVectors(angles, localnormal, NULL, false);
10532 AngleVectors(angles, planes[0], planes[2], planes[4]);
10533 VectorNegate(planes[0], planes[1]);
10534 VectorNegate(planes[2], planes[3]);
10535 VectorNegate(planes[4], planes[5]);
10536 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10537 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10538 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10539 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10540 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10541 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10546 matrix4x4_t forwardprojection;
10547 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10548 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10553 float projectionvector[4][3];
10554 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10555 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10556 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10557 projectionvector[0][0] = planes[0][0] * ilocalsize;
10558 projectionvector[0][1] = planes[1][0] * ilocalsize;
10559 projectionvector[0][2] = planes[2][0] * ilocalsize;
10560 projectionvector[1][0] = planes[0][1] * ilocalsize;
10561 projectionvector[1][1] = planes[1][1] * ilocalsize;
10562 projectionvector[1][2] = planes[2][1] * ilocalsize;
10563 projectionvector[2][0] = planes[0][2] * ilocalsize;
10564 projectionvector[2][1] = planes[1][2] * ilocalsize;
10565 projectionvector[2][2] = planes[2][2] * ilocalsize;
10566 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10567 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10568 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10569 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10573 dynamic = model->surfmesh.isanimated;
10574 numsurfacelist = model->nummodelsurfaces;
10575 surfacelist = model->sortedmodelsurfaces;
10576 surfaces = model->data_surfaces;
10579 bih_triangles_count = -1;
10582 if(model->render_bih.numleafs)
10583 bih = &model->render_bih;
10584 else if(model->collision_bih.numleafs)
10585 bih = &model->collision_bih;
10588 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10589 if(bih_triangles_count == 0)
10591 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10593 if(bih_triangles_count > 0)
10595 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10597 surfaceindex = bih_surfaces[triangleindex];
10598 surface = surfaces + surfaceindex;
10599 texture = surface->texture;
10600 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10602 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10604 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10609 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10611 surfaceindex = surfacelist[surfacelistindex];
10612 surface = surfaces + surfaceindex;
10613 // check cull box first because it rejects more than any other check
10614 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10616 // skip transparent surfaces
10617 texture = surface->texture;
10618 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10620 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10622 numtriangles = surface->num_triangles;
10623 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10624 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10629 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10630 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)
10632 int renderentityindex;
10633 float worldmins[3];
10634 float worldmaxs[3];
10635 entity_render_t *ent;
10637 if (!cl_decals_newsystem.integer)
10640 worldmins[0] = worldorigin[0] - worldsize;
10641 worldmins[1] = worldorigin[1] - worldsize;
10642 worldmins[2] = worldorigin[2] - worldsize;
10643 worldmaxs[0] = worldorigin[0] + worldsize;
10644 worldmaxs[1] = worldorigin[1] + worldsize;
10645 worldmaxs[2] = worldorigin[2] + worldsize;
10647 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10649 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10651 ent = r_refdef.scene.entities[renderentityindex];
10652 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10655 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10659 typedef struct r_decalsystem_splatqueue_s
10661 vec3_t worldorigin;
10662 vec3_t worldnormal;
10668 r_decalsystem_splatqueue_t;
10670 int r_decalsystem_numqueued = 0;
10671 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10673 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)
10675 r_decalsystem_splatqueue_t *queue;
10677 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10680 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10681 VectorCopy(worldorigin, queue->worldorigin);
10682 VectorCopy(worldnormal, queue->worldnormal);
10683 Vector4Set(queue->color, r, g, b, a);
10684 Vector4Set(queue->tcrange, s1, t1, s2, t2);
10685 queue->worldsize = worldsize;
10686 queue->decalsequence = cl.decalsequence++;
10689 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10692 r_decalsystem_splatqueue_t *queue;
10694 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10695 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);
10696 r_decalsystem_numqueued = 0;
10699 extern cvar_t cl_decals_max;
10700 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10703 decalsystem_t *decalsystem = &ent->decalsystem;
10710 if (!decalsystem->numdecals)
10713 if (r_showsurfaces.integer)
10716 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10718 R_DecalSystem_Reset(decalsystem);
10722 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10723 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10725 if (decalsystem->lastupdatetime)
10726 frametime = (cl.time - decalsystem->lastupdatetime);
10729 decalsystem->lastupdatetime = cl.time;
10730 decal = decalsystem->decals;
10731 numdecals = decalsystem->numdecals;
10733 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10735 if (decal->color4f[0][3])
10737 decal->lived += frametime;
10738 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10740 memset(decal, 0, sizeof(*decal));
10741 if (decalsystem->freedecal > i)
10742 decalsystem->freedecal = i;
10746 decal = decalsystem->decals;
10747 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10750 // collapse the array by shuffling the tail decals into the gaps
10753 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10754 decalsystem->freedecal++;
10755 if (decalsystem->freedecal == numdecals)
10757 decal[decalsystem->freedecal] = decal[--numdecals];
10760 decalsystem->numdecals = numdecals;
10762 if (numdecals <= 0)
10764 // if there are no decals left, reset decalsystem
10765 R_DecalSystem_Reset(decalsystem);
10769 extern skinframe_t *decalskinframe;
10770 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10773 decalsystem_t *decalsystem = &ent->decalsystem;
10782 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10785 numdecals = decalsystem->numdecals;
10789 if (r_showsurfaces.integer)
10792 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10794 R_DecalSystem_Reset(decalsystem);
10798 // if the model is static it doesn't matter what value we give for
10799 // wantnormals and wanttangents, so this logic uses only rules applicable
10800 // to a model, knowing that they are meaningless otherwise
10801 if (ent == r_refdef.scene.worldentity)
10802 RSurf_ActiveWorldEntity();
10804 RSurf_ActiveModelEntity(ent, false, false, false);
10806 decalsystem->lastupdatetime = cl.time;
10807 decal = decalsystem->decals;
10809 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10811 // update vertex positions for animated models
10812 v3f = decalsystem->vertex3f;
10813 c4f = decalsystem->color4f;
10814 t2f = decalsystem->texcoord2f;
10815 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10817 if (!decal->color4f[0][3])
10820 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10823 // update color values for fading decals
10824 if (decal->lived >= cl_decals_time.value)
10825 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10829 c4f[ 0] = decal->color4f[0][0] * alpha;
10830 c4f[ 1] = decal->color4f[0][1] * alpha;
10831 c4f[ 2] = decal->color4f[0][2] * alpha;
10833 c4f[ 4] = decal->color4f[1][0] * alpha;
10834 c4f[ 5] = decal->color4f[1][1] * alpha;
10835 c4f[ 6] = decal->color4f[1][2] * alpha;
10837 c4f[ 8] = decal->color4f[2][0] * alpha;
10838 c4f[ 9] = decal->color4f[2][1] * alpha;
10839 c4f[10] = decal->color4f[2][2] * alpha;
10842 t2f[0] = decal->texcoord2f[0][0];
10843 t2f[1] = decal->texcoord2f[0][1];
10844 t2f[2] = decal->texcoord2f[1][0];
10845 t2f[3] = decal->texcoord2f[1][1];
10846 t2f[4] = decal->texcoord2f[2][0];
10847 t2f[5] = decal->texcoord2f[2][1];
10849 // update vertex positions for animated models
10850 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10852 e = rsurface.modelelement3i + 3*decal->triangleindex;
10853 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10854 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10855 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10859 VectorCopy(decal->vertex3f[0], v3f);
10860 VectorCopy(decal->vertex3f[1], v3f + 3);
10861 VectorCopy(decal->vertex3f[2], v3f + 6);
10864 if (r_refdef.fogenabled)
10866 alpha = RSurf_FogVertex(v3f);
10867 VectorScale(c4f, alpha, c4f);
10868 alpha = RSurf_FogVertex(v3f + 3);
10869 VectorScale(c4f + 4, alpha, c4f + 4);
10870 alpha = RSurf_FogVertex(v3f + 6);
10871 VectorScale(c4f + 8, alpha, c4f + 8);
10882 r_refdef.stats.drawndecals += numtris;
10884 // now render the decals all at once
10885 // (this assumes they all use one particle font texture!)
10886 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);
10887 // R_Mesh_ResetTextureState();
10888 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10889 GL_DepthMask(false);
10890 GL_DepthRange(0, 1);
10891 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10892 GL_DepthTest(true);
10893 GL_CullFace(GL_NONE);
10894 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10895 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10896 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10900 static void R_DrawModelDecals(void)
10904 // fade faster when there are too many decals
10905 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10906 for (i = 0;i < r_refdef.scene.numentities;i++)
10907 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10909 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10910 for (i = 0;i < r_refdef.scene.numentities;i++)
10911 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10912 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10914 R_DecalSystem_ApplySplatEntitiesQueue();
10916 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10917 for (i = 0;i < r_refdef.scene.numentities;i++)
10918 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10920 r_refdef.stats.totaldecals += numdecals;
10922 if (r_showsurfaces.integer)
10925 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10927 for (i = 0;i < r_refdef.scene.numentities;i++)
10929 if (!r_refdef.viewcache.entityvisible[i])
10931 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10932 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10936 extern cvar_t mod_collision_bih;
10937 void R_DrawDebugModel(void)
10939 entity_render_t *ent = rsurface.entity;
10940 int i, j, k, l, flagsmask;
10941 const msurface_t *surface;
10942 dp_model_t *model = ent->model;
10945 switch(vid.renderpath)
10947 case RENDERPATH_GL11:
10948 case RENDERPATH_GL13:
10949 case RENDERPATH_GL20:
10951 case RENDERPATH_D3D9:
10952 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10954 case RENDERPATH_D3D10:
10955 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10957 case RENDERPATH_D3D11:
10958 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10960 case RENDERPATH_SOFT:
10961 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10963 case RENDERPATH_GLES2:
10964 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10968 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
10970 // R_Mesh_ResetTextureState();
10971 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10972 GL_DepthRange(0, 1);
10973 GL_DepthTest(!r_showdisabledepthtest.integer);
10974 GL_DepthMask(false);
10975 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10977 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
10981 qboolean cullbox = ent == r_refdef.scene.worldentity;
10982 const q3mbrush_t *brush;
10983 const bih_t *bih = &model->collision_bih;
10984 const bih_leaf_t *bihleaf;
10985 float vertex3f[3][3];
10986 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
10988 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
10990 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
10992 switch (bihleaf->type)
10995 brush = model->brush.data_brushes + bihleaf->itemindex;
10996 if (brush->colbrushf && brush->colbrushf->numtriangles)
10998 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);
10999 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11000 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11003 case BIH_COLLISIONTRIANGLE:
11004 triangleindex = bihleaf->itemindex;
11005 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11006 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11007 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11008 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);
11009 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11010 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11012 case BIH_RENDERTRIANGLE:
11013 triangleindex = bihleaf->itemindex;
11014 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11015 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11016 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11017 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);
11018 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11019 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11025 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11027 if (r_showtris.integer || (r_shownormals.value != 0))
11029 if (r_showdisabledepthtest.integer)
11031 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11032 GL_DepthMask(false);
11036 GL_BlendFunc(GL_ONE, GL_ZERO);
11037 GL_DepthMask(true);
11039 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11041 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11043 rsurface.texture = R_GetCurrentTexture(surface->texture);
11044 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11046 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11047 if (r_showtris.value > 0)
11049 if (!rsurface.texture->currentlayers->depthmask)
11050 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11051 else if (ent == r_refdef.scene.worldentity)
11052 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11054 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11055 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11056 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
11058 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
11061 if (r_shownormals.value < 0)
11063 qglBegin(GL_LINES);
11064 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11066 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11067 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11068 qglVertex3f(v[0], v[1], v[2]);
11069 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11070 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11071 qglVertex3f(v[0], v[1], v[2]);
11076 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11078 qglBegin(GL_LINES);
11079 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11081 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11082 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11083 qglVertex3f(v[0], v[1], v[2]);
11084 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11085 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11086 qglVertex3f(v[0], v[1], v[2]);
11090 qglBegin(GL_LINES);
11091 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11093 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11094 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11095 qglVertex3f(v[0], v[1], v[2]);
11096 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11097 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11098 qglVertex3f(v[0], v[1], v[2]);
11102 qglBegin(GL_LINES);
11103 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11105 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11106 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11107 qglVertex3f(v[0], v[1], v[2]);
11108 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11109 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11110 qglVertex3f(v[0], v[1], v[2]);
11117 rsurface.texture = NULL;
11121 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11122 int r_maxsurfacelist = 0;
11123 const msurface_t **r_surfacelist = NULL;
11124 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11126 int i, j, endj, flagsmask;
11127 dp_model_t *model = r_refdef.scene.worldmodel;
11128 msurface_t *surfaces;
11129 unsigned char *update;
11130 int numsurfacelist = 0;
11134 if (r_maxsurfacelist < model->num_surfaces)
11136 r_maxsurfacelist = model->num_surfaces;
11138 Mem_Free((msurface_t**)r_surfacelist);
11139 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11142 RSurf_ActiveWorldEntity();
11144 surfaces = model->data_surfaces;
11145 update = model->brushq1.lightmapupdateflags;
11147 // update light styles on this submodel
11148 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11150 model_brush_lightstyleinfo_t *style;
11151 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11153 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11155 int *list = style->surfacelist;
11156 style->value = r_refdef.scene.lightstylevalue[style->style];
11157 for (j = 0;j < style->numsurfaces;j++)
11158 update[list[j]] = true;
11163 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11167 R_DrawDebugModel();
11168 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11172 rsurface.lightmaptexture = NULL;
11173 rsurface.deluxemaptexture = NULL;
11174 rsurface.uselightmaptexture = false;
11175 rsurface.texture = NULL;
11176 rsurface.rtlight = NULL;
11177 numsurfacelist = 0;
11178 // add visible surfaces to draw list
11179 for (i = 0;i < model->nummodelsurfaces;i++)
11181 j = model->sortedmodelsurfaces[i];
11182 if (r_refdef.viewcache.world_surfacevisible[j])
11183 r_surfacelist[numsurfacelist++] = surfaces + j;
11185 // update lightmaps if needed
11186 if (model->brushq1.firstrender)
11188 model->brushq1.firstrender = false;
11189 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11191 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11195 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11196 if (r_refdef.viewcache.world_surfacevisible[j])
11198 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11200 // don't do anything if there were no surfaces
11201 if (!numsurfacelist)
11203 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11206 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11208 // add to stats if desired
11209 if (r_speeds.integer && !skysurfaces && !depthonly)
11211 r_refdef.stats.world_surfaces += numsurfacelist;
11212 for (j = 0;j < numsurfacelist;j++)
11213 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11216 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11219 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11221 int i, j, endj, flagsmask;
11222 dp_model_t *model = ent->model;
11223 msurface_t *surfaces;
11224 unsigned char *update;
11225 int numsurfacelist = 0;
11229 if (r_maxsurfacelist < model->num_surfaces)
11231 r_maxsurfacelist = model->num_surfaces;
11233 Mem_Free((msurface_t **)r_surfacelist);
11234 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11237 // if the model is static it doesn't matter what value we give for
11238 // wantnormals and wanttangents, so this logic uses only rules applicable
11239 // to a model, knowing that they are meaningless otherwise
11240 if (ent == r_refdef.scene.worldentity)
11241 RSurf_ActiveWorldEntity();
11242 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11243 RSurf_ActiveModelEntity(ent, false, false, false);
11245 RSurf_ActiveModelEntity(ent, true, true, true);
11246 else if (depthonly)
11248 switch (vid.renderpath)
11250 case RENDERPATH_GL20:
11251 case RENDERPATH_D3D9:
11252 case RENDERPATH_D3D10:
11253 case RENDERPATH_D3D11:
11254 case RENDERPATH_SOFT:
11255 case RENDERPATH_GLES2:
11256 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11258 case RENDERPATH_GL13:
11259 case RENDERPATH_GL11:
11260 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11266 switch (vid.renderpath)
11268 case RENDERPATH_GL20:
11269 case RENDERPATH_D3D9:
11270 case RENDERPATH_D3D10:
11271 case RENDERPATH_D3D11:
11272 case RENDERPATH_SOFT:
11273 case RENDERPATH_GLES2:
11274 RSurf_ActiveModelEntity(ent, true, true, false);
11276 case RENDERPATH_GL13:
11277 case RENDERPATH_GL11:
11278 RSurf_ActiveModelEntity(ent, true, false, false);
11283 surfaces = model->data_surfaces;
11284 update = model->brushq1.lightmapupdateflags;
11286 // update light styles
11287 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11289 model_brush_lightstyleinfo_t *style;
11290 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11292 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11294 int *list = style->surfacelist;
11295 style->value = r_refdef.scene.lightstylevalue[style->style];
11296 for (j = 0;j < style->numsurfaces;j++)
11297 update[list[j]] = true;
11302 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11306 R_DrawDebugModel();
11307 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11311 rsurface.lightmaptexture = NULL;
11312 rsurface.deluxemaptexture = NULL;
11313 rsurface.uselightmaptexture = false;
11314 rsurface.texture = NULL;
11315 rsurface.rtlight = NULL;
11316 numsurfacelist = 0;
11317 // add visible surfaces to draw list
11318 for (i = 0;i < model->nummodelsurfaces;i++)
11319 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11320 // don't do anything if there were no surfaces
11321 if (!numsurfacelist)
11323 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11326 // update lightmaps if needed
11330 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11335 R_BuildLightMap(ent, surfaces + j);
11340 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11342 R_BuildLightMap(ent, surfaces + j);
11343 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11345 // add to stats if desired
11346 if (r_speeds.integer && !skysurfaces && !depthonly)
11348 r_refdef.stats.entities_surfaces += numsurfacelist;
11349 for (j = 0;j < numsurfacelist;j++)
11350 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11353 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11356 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11358 static texture_t texture;
11359 static msurface_t surface;
11360 const msurface_t *surfacelist = &surface;
11362 // fake enough texture and surface state to render this geometry
11364 texture.update_lastrenderframe = -1; // regenerate this texture
11365 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11366 texture.currentskinframe = skinframe;
11367 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11368 texture.offsetmapping = OFFSETMAPPING_OFF;
11369 texture.offsetscale = 1;
11370 texture.specularscalemod = 1;
11371 texture.specularpowermod = 1;
11373 surface.texture = &texture;
11374 surface.num_triangles = numtriangles;
11375 surface.num_firsttriangle = firsttriangle;
11376 surface.num_vertices = numvertices;
11377 surface.num_firstvertex = firstvertex;
11380 rsurface.texture = R_GetCurrentTexture(surface.texture);
11381 rsurface.lightmaptexture = NULL;
11382 rsurface.deluxemaptexture = NULL;
11383 rsurface.uselightmaptexture = false;
11384 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11387 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)
11389 static msurface_t surface;
11390 const msurface_t *surfacelist = &surface;
11392 // fake enough texture and surface state to render this geometry
11393 surface.texture = texture;
11394 surface.num_triangles = numtriangles;
11395 surface.num_firsttriangle = firsttriangle;
11396 surface.num_vertices = numvertices;
11397 surface.num_firstvertex = firstvertex;
11400 rsurface.texture = R_GetCurrentTexture(surface.texture);
11401 rsurface.lightmaptexture = NULL;
11402 rsurface.deluxemaptexture = NULL;
11403 rsurface.uselightmaptexture = false;
11404 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);