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_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
119 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
120 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"};
122 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
123 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
124 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
125 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
126 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
127 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
128 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
129 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
131 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)"};
132 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"};
134 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
135 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
136 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
137 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
138 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
140 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
141 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
142 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
144 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)"};
145 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
146 cvar_t r_glsl_offsetmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
147 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
148 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
149 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
150 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
151 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)"};
152 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)"};
153 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)"};
154 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)"};
155 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)"};
156 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)"};
157 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)"};
158 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)"};
160 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)"};
161 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
162 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"};
163 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
164 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
165 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
167 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
168 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
169 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
170 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
172 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
173 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
174 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
175 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
176 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
177 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
178 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
180 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
181 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
182 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
183 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)"};
184 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
185 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
186 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
187 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
188 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
189 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
191 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"};
193 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"};
195 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
197 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
198 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"};
199 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
200 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
201 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
202 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
203 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)"};
204 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
205 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
207 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
208 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"};
210 cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer."};
212 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)"};
214 extern cvar_t v_glslgamma;
216 extern qboolean v_flipped_state;
218 static struct r_bloomstate_s
223 int bloomwidth, bloomheight;
225 int screentexturewidth, screentextureheight;
226 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
228 int bloomtexturewidth, bloomtextureheight;
229 rtexture_t *texture_bloom;
231 // arrays for rendering the screen passes
232 float screentexcoord2f[8];
233 float bloomtexcoord2f[8];
234 float offsettexcoord2f[8];
236 r_viewport_t viewport;
240 r_waterstate_t r_waterstate;
242 /// shadow volume bsp struct with automatically growing nodes buffer
245 rtexture_t *r_texture_blanknormalmap;
246 rtexture_t *r_texture_white;
247 rtexture_t *r_texture_grey128;
248 rtexture_t *r_texture_black;
249 rtexture_t *r_texture_notexture;
250 rtexture_t *r_texture_whitecube;
251 rtexture_t *r_texture_normalizationcube;
252 rtexture_t *r_texture_fogattenuation;
253 rtexture_t *r_texture_fogheighttexture;
254 rtexture_t *r_texture_gammaramps;
255 unsigned int r_texture_gammaramps_serial;
256 //rtexture_t *r_texture_fogintensity;
257 rtexture_t *r_texture_reflectcube;
259 // TODO: hash lookups?
260 typedef struct cubemapinfo_s
267 int r_texture_numcubemaps;
268 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
270 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
271 unsigned int r_numqueries;
272 unsigned int r_maxqueries;
274 typedef struct r_qwskincache_s
276 char name[MAX_QPATH];
277 skinframe_t *skinframe;
281 static r_qwskincache_t *r_qwskincache;
282 static int r_qwskincache_size;
284 /// vertex coordinates for a quad that covers the screen exactly
285 extern const float r_screenvertex3f[12];
286 extern const float r_d3dscreenvertex3f[12];
287 const float r_screenvertex3f[12] =
294 const float r_d3dscreenvertex3f[12] =
302 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
305 for (i = 0;i < verts;i++)
316 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
319 for (i = 0;i < verts;i++)
329 // FIXME: move this to client?
332 if (gamemode == GAME_NEHAHRA)
334 Cvar_Set("gl_fogenable", "0");
335 Cvar_Set("gl_fogdensity", "0.2");
336 Cvar_Set("gl_fogred", "0.3");
337 Cvar_Set("gl_foggreen", "0.3");
338 Cvar_Set("gl_fogblue", "0.3");
340 r_refdef.fog_density = 0;
341 r_refdef.fog_red = 0;
342 r_refdef.fog_green = 0;
343 r_refdef.fog_blue = 0;
344 r_refdef.fog_alpha = 1;
345 r_refdef.fog_start = 0;
346 r_refdef.fog_end = 16384;
347 r_refdef.fog_height = 1<<30;
348 r_refdef.fog_fadedepth = 128;
349 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
352 static void R_BuildBlankTextures(void)
354 unsigned char data[4];
355 data[2] = 128; // normal X
356 data[1] = 128; // normal Y
357 data[0] = 255; // normal Z
358 data[3] = 128; // height
359 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
364 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
369 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
374 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
377 static void R_BuildNoTexture(void)
380 unsigned char pix[16][16][4];
381 // this makes a light grey/dark grey checkerboard texture
382 for (y = 0;y < 16;y++)
384 for (x = 0;x < 16;x++)
386 if ((y < 8) ^ (x < 8))
402 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
405 static void R_BuildWhiteCube(void)
407 unsigned char data[6*1*1*4];
408 memset(data, 255, sizeof(data));
409 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
412 static void R_BuildNormalizationCube(void)
416 vec_t s, t, intensity;
419 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
420 for (side = 0;side < 6;side++)
422 for (y = 0;y < NORMSIZE;y++)
424 for (x = 0;x < NORMSIZE;x++)
426 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
427 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
462 intensity = 127.0f / sqrt(DotProduct(v, v));
463 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
464 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
465 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
466 data[((side*64+y)*64+x)*4+3] = 255;
470 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
474 static void R_BuildFogTexture(void)
478 unsigned char data1[FOGWIDTH][4];
479 //unsigned char data2[FOGWIDTH][4];
482 r_refdef.fogmasktable_start = r_refdef.fog_start;
483 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
484 r_refdef.fogmasktable_range = r_refdef.fogrange;
485 r_refdef.fogmasktable_density = r_refdef.fog_density;
487 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
488 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
490 d = (x * r - r_refdef.fogmasktable_start);
491 if(developer_extra.integer)
492 Con_DPrintf("%f ", d);
494 if (r_fog_exp2.integer)
495 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
497 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
498 if(developer_extra.integer)
499 Con_DPrintf(" : %f ", alpha);
500 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
501 if(developer_extra.integer)
502 Con_DPrintf(" = %f\n", alpha);
503 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
506 for (x = 0;x < FOGWIDTH;x++)
508 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
513 //data2[x][0] = 255 - b;
514 //data2[x][1] = 255 - b;
515 //data2[x][2] = 255 - b;
518 if (r_texture_fogattenuation)
520 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
521 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
525 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
526 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
530 static void R_BuildFogHeightTexture(void)
532 unsigned char *inpixels;
540 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
541 if (r_refdef.fogheighttexturename[0])
542 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
545 r_refdef.fog_height_tablesize = 0;
546 if (r_texture_fogheighttexture)
547 R_FreeTexture(r_texture_fogheighttexture);
548 r_texture_fogheighttexture = NULL;
549 if (r_refdef.fog_height_table2d)
550 Mem_Free(r_refdef.fog_height_table2d);
551 r_refdef.fog_height_table2d = NULL;
552 if (r_refdef.fog_height_table1d)
553 Mem_Free(r_refdef.fog_height_table1d);
554 r_refdef.fog_height_table1d = NULL;
558 r_refdef.fog_height_tablesize = size;
559 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
560 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
561 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
563 // LordHavoc: now the magic - what is that table2d for? it is a cooked
564 // average fog color table accounting for every fog layer between a point
565 // and the camera. (Note: attenuation is handled separately!)
566 for (y = 0;y < size;y++)
568 for (x = 0;x < size;x++)
574 for (j = x;j <= y;j++)
576 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
582 for (j = x;j >= y;j--)
584 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
589 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
590 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
591 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
592 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
595 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
598 //=======================================================================================================================================================
600 static const char *builtinshaderstring =
601 #include "shader_glsl.h"
604 const char *builtinhlslshaderstring =
605 #include "shader_hlsl.h"
608 char *glslshaderstring = NULL;
609 char *hlslshaderstring = NULL;
611 //=======================================================================================================================================================
613 typedef struct shaderpermutationinfo_s
618 shaderpermutationinfo_t;
620 typedef struct shadermodeinfo_s
622 const char *vertexfilename;
623 const char *geometryfilename;
624 const char *fragmentfilename;
630 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
631 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
633 {"#define USEDIFFUSE\n", " diffuse"},
634 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
635 {"#define USEVIEWTINT\n", " viewtint"},
636 {"#define USECOLORMAPPING\n", " colormapping"},
637 {"#define USESATURATION\n", " saturation"},
638 {"#define USEFOGINSIDE\n", " foginside"},
639 {"#define USEFOGOUTSIDE\n", " fogoutside"},
640 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
641 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
642 {"#define USEGAMMARAMPS\n", " gammaramps"},
643 {"#define USECUBEFILTER\n", " cubefilter"},
644 {"#define USEGLOW\n", " glow"},
645 {"#define USEBLOOM\n", " bloom"},
646 {"#define USESPECULAR\n", " specular"},
647 {"#define USEPOSTPROCESSING\n", " postprocessing"},
648 {"#define USEREFLECTION\n", " reflection"},
649 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
650 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
651 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
652 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
653 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
654 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
655 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
656 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
657 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
658 {"#define USEALPHAKILL\n", " alphakill"},
659 {"#define USEREFLECTCUBE\n", " reflectcube"},
660 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
661 {"#define USEBOUNCEGRID\n", " bouncegrid"},
662 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
665 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
666 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
668 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
669 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
670 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
671 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
672 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
673 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
674 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
675 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
676 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
677 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
678 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
679 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
680 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
681 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
682 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
683 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
686 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
688 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
689 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
690 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
691 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
692 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
693 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
694 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
695 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
696 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
697 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
698 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
699 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
700 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
701 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
702 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
703 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
706 struct r_glsl_permutation_s;
707 typedef struct r_glsl_permutation_s
710 struct r_glsl_permutation_s *hashnext;
712 unsigned int permutation;
714 /// indicates if we have tried compiling this permutation already
716 /// 0 if compilation failed
718 // texture units assigned to each detected uniform
719 int tex_Texture_First;
720 int tex_Texture_Second;
721 int tex_Texture_GammaRamps;
722 int tex_Texture_Normal;
723 int tex_Texture_Color;
724 int tex_Texture_Gloss;
725 int tex_Texture_Glow;
726 int tex_Texture_SecondaryNormal;
727 int tex_Texture_SecondaryColor;
728 int tex_Texture_SecondaryGloss;
729 int tex_Texture_SecondaryGlow;
730 int tex_Texture_Pants;
731 int tex_Texture_Shirt;
732 int tex_Texture_FogHeightTexture;
733 int tex_Texture_FogMask;
734 int tex_Texture_Lightmap;
735 int tex_Texture_Deluxemap;
736 int tex_Texture_Attenuation;
737 int tex_Texture_Cube;
738 int tex_Texture_Refraction;
739 int tex_Texture_Reflection;
740 int tex_Texture_ShadowMap2D;
741 int tex_Texture_CubeProjection;
742 int tex_Texture_ScreenDepth;
743 int tex_Texture_ScreenNormalMap;
744 int tex_Texture_ScreenDiffuse;
745 int tex_Texture_ScreenSpecular;
746 int tex_Texture_ReflectMask;
747 int tex_Texture_ReflectCube;
748 int tex_Texture_BounceGrid;
749 /// locations of detected uniforms in program object, or -1 if not found
750 int loc_Texture_First;
751 int loc_Texture_Second;
752 int loc_Texture_GammaRamps;
753 int loc_Texture_Normal;
754 int loc_Texture_Color;
755 int loc_Texture_Gloss;
756 int loc_Texture_Glow;
757 int loc_Texture_SecondaryNormal;
758 int loc_Texture_SecondaryColor;
759 int loc_Texture_SecondaryGloss;
760 int loc_Texture_SecondaryGlow;
761 int loc_Texture_Pants;
762 int loc_Texture_Shirt;
763 int loc_Texture_FogHeightTexture;
764 int loc_Texture_FogMask;
765 int loc_Texture_Lightmap;
766 int loc_Texture_Deluxemap;
767 int loc_Texture_Attenuation;
768 int loc_Texture_Cube;
769 int loc_Texture_Refraction;
770 int loc_Texture_Reflection;
771 int loc_Texture_ShadowMap2D;
772 int loc_Texture_CubeProjection;
773 int loc_Texture_ScreenDepth;
774 int loc_Texture_ScreenNormalMap;
775 int loc_Texture_ScreenDiffuse;
776 int loc_Texture_ScreenSpecular;
777 int loc_Texture_ReflectMask;
778 int loc_Texture_ReflectCube;
779 int loc_Texture_BounceGrid;
781 int loc_BloomBlur_Parameters;
783 int loc_Color_Ambient;
784 int loc_Color_Diffuse;
785 int loc_Color_Specular;
789 int loc_DeferredColor_Ambient;
790 int loc_DeferredColor_Diffuse;
791 int loc_DeferredColor_Specular;
792 int loc_DeferredMod_Diffuse;
793 int loc_DeferredMod_Specular;
794 int loc_DistortScaleRefractReflect;
797 int loc_FogHeightFade;
799 int loc_FogPlaneViewDist;
800 int loc_FogRangeRecip;
803 int loc_LightPosition;
804 int loc_OffsetMapping_ScaleSteps;
806 int loc_ReflectColor;
807 int loc_ReflectFactor;
808 int loc_ReflectOffset;
809 int loc_RefractColor;
811 int loc_ScreenCenterRefractReflect;
812 int loc_ScreenScaleRefractReflect;
813 int loc_ScreenToDepth;
814 int loc_ShadowMap_Parameters;
815 int loc_ShadowMap_TextureScale;
816 int loc_SpecularPower;
821 int loc_ViewTintColor;
823 int loc_ModelToLight;
825 int loc_BackgroundTexMatrix;
826 int loc_ModelViewProjectionMatrix;
827 int loc_ModelViewMatrix;
828 int loc_PixelToScreenTexCoord;
829 int loc_ModelToReflectCube;
830 int loc_ShadowMapMatrix;
831 int loc_BloomColorSubtract;
832 int loc_NormalmapScrollBlend;
833 int loc_BounceGridMatrix;
834 int loc_BounceGridIntensity;
836 r_glsl_permutation_t;
838 #define SHADERPERMUTATION_HASHSIZE 256
841 // non-degradable "lightweight" shader parameters to keep the permutations simpler
842 // these can NOT degrade! only use for simple stuff
845 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
846 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
847 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
848 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
849 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
850 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
851 SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
853 #define SHADERSTATICPARMS_COUNT 7
855 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
856 static int shaderstaticparms_count = 0;
858 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
859 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
860 qboolean R_CompileShader_CheckStaticParms(void)
862 static int r_compileshader_staticparms_save[1];
863 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
864 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
867 if (r_glsl_saturation_redcompensate.integer)
868 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
869 if (r_glsl_vertextextureblend_usebothalphas.integer)
870 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
871 if (r_shadow_glossexact.integer)
872 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
873 if (r_glsl_postprocess.integer)
875 if (r_glsl_postprocess_uservec1_enable.integer)
876 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
877 if (r_glsl_postprocess_uservec2_enable.integer)
878 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
879 if (r_glsl_postprocess_uservec3_enable.integer)
880 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
881 if (r_glsl_postprocess_uservec4_enable.integer)
882 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
884 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
887 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
888 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
889 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
891 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
892 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
894 shaderstaticparms_count = 0;
897 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
898 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
899 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
900 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
901 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
902 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
903 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
906 /// information about each possible shader permutation
907 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
908 /// currently selected permutation
909 r_glsl_permutation_t *r_glsl_permutation;
910 /// storage for permutations linked in the hash table
911 memexpandablearray_t r_glsl_permutationarray;
913 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
915 //unsigned int hashdepth = 0;
916 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
917 r_glsl_permutation_t *p;
918 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
920 if (p->mode == mode && p->permutation == permutation)
922 //if (hashdepth > 10)
923 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
928 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
930 p->permutation = permutation;
931 p->hashnext = r_glsl_permutationhash[mode][hashindex];
932 r_glsl_permutationhash[mode][hashindex] = p;
933 //if (hashdepth > 10)
934 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
938 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
941 if (!filename || !filename[0])
943 if (!strcmp(filename, "glsl/default.glsl"))
945 if (!glslshaderstring)
947 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
948 if (glslshaderstring)
949 Con_DPrintf("Loading shaders from file %s...\n", filename);
951 glslshaderstring = (char *)builtinshaderstring;
953 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
954 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
957 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
960 if (printfromdisknotice)
961 Con_DPrintf("from disk %s... ", filename);
967 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
971 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
972 char *vertexstring, *geometrystring, *fragmentstring;
973 char permutationname[256];
974 int vertstrings_count = 0;
975 int geomstrings_count = 0;
976 int fragstrings_count = 0;
977 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
978 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
979 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
986 permutationname[0] = 0;
987 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
988 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
989 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
991 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
993 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
994 if(vid.support.gl20shaders130)
996 vertstrings_list[vertstrings_count++] = "#version 130\n";
997 geomstrings_list[geomstrings_count++] = "#version 130\n";
998 fragstrings_list[fragstrings_count++] = "#version 130\n";
999 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1000 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1001 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1004 // the first pretext is which type of shader to compile as
1005 // (later these will all be bound together as a program object)
1006 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1007 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1008 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1010 // the second pretext is the mode (for example a light source)
1011 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1012 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1013 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1014 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1016 // now add all the permutation pretexts
1017 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1019 if (permutation & (1<<i))
1021 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1022 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1023 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1024 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1028 // keep line numbers correct
1029 vertstrings_list[vertstrings_count++] = "\n";
1030 geomstrings_list[geomstrings_count++] = "\n";
1031 fragstrings_list[fragstrings_count++] = "\n";
1036 R_CompileShader_AddStaticParms(mode, permutation);
1037 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1038 vertstrings_count += shaderstaticparms_count;
1039 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1040 geomstrings_count += shaderstaticparms_count;
1041 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1042 fragstrings_count += shaderstaticparms_count;
1044 // now append the shader text itself
1045 vertstrings_list[vertstrings_count++] = vertexstring;
1046 geomstrings_list[geomstrings_count++] = geometrystring;
1047 fragstrings_list[fragstrings_count++] = fragmentstring;
1049 // if any sources were NULL, clear the respective list
1051 vertstrings_count = 0;
1052 if (!geometrystring)
1053 geomstrings_count = 0;
1054 if (!fragmentstring)
1055 fragstrings_count = 0;
1057 // compile the shader program
1058 if (vertstrings_count + geomstrings_count + fragstrings_count)
1059 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1063 qglUseProgram(p->program);CHECKGLERROR
1064 // look up all the uniform variable names we care about, so we don't
1065 // have to look them up every time we set them
1067 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1068 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1069 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1070 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1071 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1072 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1073 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1074 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1075 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1076 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1077 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1078 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1079 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1080 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1081 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1082 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1083 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1084 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1085 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1086 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1087 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1088 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1089 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1090 p->loc_Texture_ScreenDepth = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1091 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1092 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1093 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1094 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1095 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1096 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1097 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1098 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1099 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1100 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1101 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1102 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1103 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1104 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1105 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1106 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1107 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1108 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1109 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1110 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1111 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1112 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1113 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1114 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1115 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1116 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1117 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1118 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1119 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1120 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1121 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1122 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1123 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1124 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1125 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1126 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1127 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1128 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1129 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1130 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1131 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1132 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1133 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1134 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1135 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1136 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1137 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1138 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1139 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1140 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1141 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1142 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1143 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1144 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1145 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1146 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1147 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1148 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1149 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1150 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1151 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1152 // initialize the samplers to refer to the texture units we use
1153 p->tex_Texture_First = -1;
1154 p->tex_Texture_Second = -1;
1155 p->tex_Texture_GammaRamps = -1;
1156 p->tex_Texture_Normal = -1;
1157 p->tex_Texture_Color = -1;
1158 p->tex_Texture_Gloss = -1;
1159 p->tex_Texture_Glow = -1;
1160 p->tex_Texture_SecondaryNormal = -1;
1161 p->tex_Texture_SecondaryColor = -1;
1162 p->tex_Texture_SecondaryGloss = -1;
1163 p->tex_Texture_SecondaryGlow = -1;
1164 p->tex_Texture_Pants = -1;
1165 p->tex_Texture_Shirt = -1;
1166 p->tex_Texture_FogHeightTexture = -1;
1167 p->tex_Texture_FogMask = -1;
1168 p->tex_Texture_Lightmap = -1;
1169 p->tex_Texture_Deluxemap = -1;
1170 p->tex_Texture_Attenuation = -1;
1171 p->tex_Texture_Cube = -1;
1172 p->tex_Texture_Refraction = -1;
1173 p->tex_Texture_Reflection = -1;
1174 p->tex_Texture_ShadowMap2D = -1;
1175 p->tex_Texture_CubeProjection = -1;
1176 p->tex_Texture_ScreenDepth = -1;
1177 p->tex_Texture_ScreenNormalMap = -1;
1178 p->tex_Texture_ScreenDiffuse = -1;
1179 p->tex_Texture_ScreenSpecular = -1;
1180 p->tex_Texture_ReflectMask = -1;
1181 p->tex_Texture_ReflectCube = -1;
1182 p->tex_Texture_BounceGrid = -1;
1184 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1185 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1186 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1187 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1188 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1189 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1190 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1191 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1192 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1193 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1194 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1195 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1196 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1197 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1198 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1199 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1200 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1201 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1202 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1203 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1204 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1205 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1206 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1207 if (p->loc_Texture_ScreenDepth >= 0) {p->tex_Texture_ScreenDepth = sampler;qglUniform1i(p->loc_Texture_ScreenDepth , sampler);sampler++;}
1208 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1209 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1210 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1211 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1212 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1213 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1215 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1218 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1222 Mem_Free(vertexstring);
1224 Mem_Free(geometrystring);
1226 Mem_Free(fragmentstring);
1229 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1231 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1232 if (r_glsl_permutation != perm)
1234 r_glsl_permutation = perm;
1235 if (!r_glsl_permutation->program)
1237 if (!r_glsl_permutation->compiled)
1238 R_GLSL_CompilePermutation(perm, mode, permutation);
1239 if (!r_glsl_permutation->program)
1241 // remove features until we find a valid permutation
1243 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1245 // reduce i more quickly whenever it would not remove any bits
1246 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1247 if (!(permutation & j))
1250 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1251 if (!r_glsl_permutation->compiled)
1252 R_GLSL_CompilePermutation(perm, mode, permutation);
1253 if (r_glsl_permutation->program)
1256 if (i >= SHADERPERMUTATION_COUNT)
1258 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1259 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1260 qglUseProgram(0);CHECKGLERROR
1261 return; // no bit left to clear, entire mode is broken
1266 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1268 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1269 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1270 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1277 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1278 extern D3DCAPS9 vid_d3d9caps;
1281 struct r_hlsl_permutation_s;
1282 typedef struct r_hlsl_permutation_s
1284 /// hash lookup data
1285 struct r_hlsl_permutation_s *hashnext;
1287 unsigned int permutation;
1289 /// indicates if we have tried compiling this permutation already
1291 /// NULL if compilation failed
1292 IDirect3DVertexShader9 *vertexshader;
1293 IDirect3DPixelShader9 *pixelshader;
1295 r_hlsl_permutation_t;
1297 typedef enum D3DVSREGISTER_e
1299 D3DVSREGISTER_TexMatrix = 0, // float4x4
1300 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1301 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1302 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1303 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1304 D3DVSREGISTER_ModelToLight = 20, // float4x4
1305 D3DVSREGISTER_EyePosition = 24,
1306 D3DVSREGISTER_FogPlane = 25,
1307 D3DVSREGISTER_LightDir = 26,
1308 D3DVSREGISTER_LightPosition = 27,
1312 typedef enum D3DPSREGISTER_e
1314 D3DPSREGISTER_Alpha = 0,
1315 D3DPSREGISTER_BloomBlur_Parameters = 1,
1316 D3DPSREGISTER_ClientTime = 2,
1317 D3DPSREGISTER_Color_Ambient = 3,
1318 D3DPSREGISTER_Color_Diffuse = 4,
1319 D3DPSREGISTER_Color_Specular = 5,
1320 D3DPSREGISTER_Color_Glow = 6,
1321 D3DPSREGISTER_Color_Pants = 7,
1322 D3DPSREGISTER_Color_Shirt = 8,
1323 D3DPSREGISTER_DeferredColor_Ambient = 9,
1324 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1325 D3DPSREGISTER_DeferredColor_Specular = 11,
1326 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1327 D3DPSREGISTER_DeferredMod_Specular = 13,
1328 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1329 D3DPSREGISTER_EyePosition = 15, // unused
1330 D3DPSREGISTER_FogColor = 16,
1331 D3DPSREGISTER_FogHeightFade = 17,
1332 D3DPSREGISTER_FogPlane = 18,
1333 D3DPSREGISTER_FogPlaneViewDist = 19,
1334 D3DPSREGISTER_FogRangeRecip = 20,
1335 D3DPSREGISTER_LightColor = 21,
1336 D3DPSREGISTER_LightDir = 22, // unused
1337 D3DPSREGISTER_LightPosition = 23,
1338 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1339 D3DPSREGISTER_PixelSize = 25,
1340 D3DPSREGISTER_ReflectColor = 26,
1341 D3DPSREGISTER_ReflectFactor = 27,
1342 D3DPSREGISTER_ReflectOffset = 28,
1343 D3DPSREGISTER_RefractColor = 29,
1344 D3DPSREGISTER_Saturation = 30,
1345 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1346 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1347 D3DPSREGISTER_ScreenToDepth = 33,
1348 D3DPSREGISTER_ShadowMap_Parameters = 34,
1349 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1350 D3DPSREGISTER_SpecularPower = 36,
1351 D3DPSREGISTER_UserVec1 = 37,
1352 D3DPSREGISTER_UserVec2 = 38,
1353 D3DPSREGISTER_UserVec3 = 39,
1354 D3DPSREGISTER_UserVec4 = 40,
1355 D3DPSREGISTER_ViewTintColor = 41,
1356 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1357 D3DPSREGISTER_BloomColorSubtract = 43,
1358 D3DPSREGISTER_ViewToLight = 44, // float4x4
1359 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1360 D3DPSREGISTER_NormalmapScrollBlend = 52,
1365 /// information about each possible shader permutation
1366 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1367 /// currently selected permutation
1368 r_hlsl_permutation_t *r_hlsl_permutation;
1369 /// storage for permutations linked in the hash table
1370 memexpandablearray_t r_hlsl_permutationarray;
1372 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1374 //unsigned int hashdepth = 0;
1375 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1376 r_hlsl_permutation_t *p;
1377 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1379 if (p->mode == mode && p->permutation == permutation)
1381 //if (hashdepth > 10)
1382 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1387 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1389 p->permutation = permutation;
1390 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1391 r_hlsl_permutationhash[mode][hashindex] = p;
1392 //if (hashdepth > 10)
1393 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1397 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1400 if (!filename || !filename[0])
1402 if (!strcmp(filename, "hlsl/default.hlsl"))
1404 if (!hlslshaderstring)
1406 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1407 if (hlslshaderstring)
1408 Con_DPrintf("Loading shaders from file %s...\n", filename);
1410 hlslshaderstring = (char *)builtinhlslshaderstring;
1412 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1413 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1414 return shaderstring;
1416 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1419 if (printfromdisknotice)
1420 Con_DPrintf("from disk %s... ", filename);
1421 return shaderstring;
1423 return shaderstring;
1427 //#include <d3dx9shader.h>
1428 //#include <d3dx9mesh.h>
1430 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1432 DWORD *vsbin = NULL;
1433 DWORD *psbin = NULL;
1434 fs_offset_t vsbinsize;
1435 fs_offset_t psbinsize;
1436 // IDirect3DVertexShader9 *vs = NULL;
1437 // IDirect3DPixelShader9 *ps = NULL;
1438 ID3DXBuffer *vslog = NULL;
1439 ID3DXBuffer *vsbuffer = NULL;
1440 ID3DXConstantTable *vsconstanttable = NULL;
1441 ID3DXBuffer *pslog = NULL;
1442 ID3DXBuffer *psbuffer = NULL;
1443 ID3DXConstantTable *psconstanttable = NULL;
1446 char temp[MAX_INPUTLINE];
1447 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1448 qboolean debugshader = gl_paranoid.integer != 0;
1449 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1450 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1453 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1454 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1456 if ((!vsbin && vertstring) || (!psbin && fragstring))
1458 const char* dllnames_d3dx9 [] =
1482 dllhandle_t d3dx9_dll = NULL;
1483 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1484 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1485 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1486 dllfunction_t d3dx9_dllfuncs[] =
1488 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1489 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1490 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1493 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1495 DWORD shaderflags = 0;
1497 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1498 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1499 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1500 if (vertstring && vertstring[0])
1504 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1505 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1506 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1507 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1510 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1513 vsbinsize = vsbuffer->GetBufferSize();
1514 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1515 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1516 vsbuffer->Release();
1520 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1521 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1525 if (fragstring && fragstring[0])
1529 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1530 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1531 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1532 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1535 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1538 psbinsize = psbuffer->GetBufferSize();
1539 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1540 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1541 psbuffer->Release();
1545 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1546 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1550 Sys_UnloadLibrary(&d3dx9_dll);
1553 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1557 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1558 if (FAILED(vsresult))
1559 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1560 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1561 if (FAILED(psresult))
1562 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1564 // free the shader data
1565 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1566 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1569 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1572 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1573 int vertstring_length = 0;
1574 int geomstring_length = 0;
1575 int fragstring_length = 0;
1577 char *vertexstring, *geometrystring, *fragmentstring;
1578 char *vertstring, *geomstring, *fragstring;
1579 char permutationname[256];
1580 char cachename[256];
1581 int vertstrings_count = 0;
1582 int geomstrings_count = 0;
1583 int fragstrings_count = 0;
1584 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1585 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1586 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1591 p->vertexshader = NULL;
1592 p->pixelshader = NULL;
1594 permutationname[0] = 0;
1596 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
1597 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1598 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1600 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1601 strlcat(cachename, "hlsl/", sizeof(cachename));
1603 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1604 vertstrings_count = 0;
1605 geomstrings_count = 0;
1606 fragstrings_count = 0;
1607 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1608 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1609 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1611 // the first pretext is which type of shader to compile as
1612 // (later these will all be bound together as a program object)
1613 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1614 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1615 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1617 // the second pretext is the mode (for example a light source)
1618 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1619 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1620 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1621 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1622 strlcat(cachename, modeinfo->name, sizeof(cachename));
1624 // now add all the permutation pretexts
1625 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1627 if (permutation & (1<<i))
1629 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1630 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1631 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1632 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1633 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1637 // keep line numbers correct
1638 vertstrings_list[vertstrings_count++] = "\n";
1639 geomstrings_list[geomstrings_count++] = "\n";
1640 fragstrings_list[fragstrings_count++] = "\n";
1645 R_CompileShader_AddStaticParms(mode, permutation);
1646 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1647 vertstrings_count += shaderstaticparms_count;
1648 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1649 geomstrings_count += shaderstaticparms_count;
1650 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1651 fragstrings_count += shaderstaticparms_count;
1653 // replace spaces in the cachename with _ characters
1654 for (i = 0;cachename[i];i++)
1655 if (cachename[i] == ' ')
1658 // now append the shader text itself
1659 vertstrings_list[vertstrings_count++] = vertexstring;
1660 geomstrings_list[geomstrings_count++] = geometrystring;
1661 fragstrings_list[fragstrings_count++] = fragmentstring;
1663 // if any sources were NULL, clear the respective list
1665 vertstrings_count = 0;
1666 if (!geometrystring)
1667 geomstrings_count = 0;
1668 if (!fragmentstring)
1669 fragstrings_count = 0;
1671 vertstring_length = 0;
1672 for (i = 0;i < vertstrings_count;i++)
1673 vertstring_length += strlen(vertstrings_list[i]);
1674 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1675 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1676 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1678 geomstring_length = 0;
1679 for (i = 0;i < geomstrings_count;i++)
1680 geomstring_length += strlen(geomstrings_list[i]);
1681 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1682 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1683 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1685 fragstring_length = 0;
1686 for (i = 0;i < fragstrings_count;i++)
1687 fragstring_length += strlen(fragstrings_list[i]);
1688 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1689 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1690 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1692 // try to load the cached shader, or generate one
1693 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1695 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1696 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1698 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1702 Mem_Free(vertstring);
1704 Mem_Free(geomstring);
1706 Mem_Free(fragstring);
1708 Mem_Free(vertexstring);
1710 Mem_Free(geometrystring);
1712 Mem_Free(fragmentstring);
1715 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1716 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1717 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);}
1718 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);}
1719 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);}
1720 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);}
1722 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1723 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1724 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);}
1725 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);}
1726 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);}
1727 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);}
1729 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1731 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1732 if (r_hlsl_permutation != perm)
1734 r_hlsl_permutation = perm;
1735 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1737 if (!r_hlsl_permutation->compiled)
1738 R_HLSL_CompilePermutation(perm, mode, permutation);
1739 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1741 // remove features until we find a valid permutation
1743 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1745 // reduce i more quickly whenever it would not remove any bits
1746 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1747 if (!(permutation & j))
1750 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1751 if (!r_hlsl_permutation->compiled)
1752 R_HLSL_CompilePermutation(perm, mode, permutation);
1753 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1756 if (i >= SHADERPERMUTATION_COUNT)
1758 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1759 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1760 return; // no bit left to clear, entire mode is broken
1764 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1765 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1767 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1768 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1769 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1773 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1775 DPSOFTRAST_SetShader(mode, permutation);
1776 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1777 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1778 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1781 void R_GLSL_Restart_f(void)
1783 unsigned int i, limit;
1784 if (glslshaderstring && glslshaderstring != builtinshaderstring)
1785 Mem_Free(glslshaderstring);
1786 glslshaderstring = NULL;
1787 if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1788 Mem_Free(hlslshaderstring);
1789 hlslshaderstring = NULL;
1790 switch(vid.renderpath)
1792 case RENDERPATH_D3D9:
1795 r_hlsl_permutation_t *p;
1796 r_hlsl_permutation = NULL;
1797 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1798 for (i = 0;i < limit;i++)
1800 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1802 if (p->vertexshader)
1803 IDirect3DVertexShader9_Release(p->vertexshader);
1805 IDirect3DPixelShader9_Release(p->pixelshader);
1806 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1809 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1813 case RENDERPATH_D3D10:
1814 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1816 case RENDERPATH_D3D11:
1817 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1819 case RENDERPATH_GL20:
1820 case RENDERPATH_GLES2:
1822 r_glsl_permutation_t *p;
1823 r_glsl_permutation = NULL;
1824 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1825 for (i = 0;i < limit;i++)
1827 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1829 GL_Backend_FreeProgram(p->program);
1830 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1833 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1836 case RENDERPATH_GL13:
1837 case RENDERPATH_GL11:
1839 case RENDERPATH_SOFT:
1844 void R_GLSL_DumpShader_f(void)
1849 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1852 FS_Print(file, "/* The engine may define the following macros:\n");
1853 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1854 for (i = 0;i < SHADERMODE_COUNT;i++)
1855 FS_Print(file, glslshadermodeinfo[i].pretext);
1856 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1857 FS_Print(file, shaderpermutationinfo[i].pretext);
1858 FS_Print(file, "*/\n");
1859 FS_Print(file, builtinshaderstring);
1861 Con_Printf("glsl/default.glsl written\n");
1864 Con_Printf("failed to write to glsl/default.glsl\n");
1866 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1869 FS_Print(file, "/* The engine may define the following macros:\n");
1870 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1871 for (i = 0;i < SHADERMODE_COUNT;i++)
1872 FS_Print(file, hlslshadermodeinfo[i].pretext);
1873 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1874 FS_Print(file, shaderpermutationinfo[i].pretext);
1875 FS_Print(file, "*/\n");
1876 FS_Print(file, builtinhlslshaderstring);
1878 Con_Printf("hlsl/default.hlsl written\n");
1881 Con_Printf("failed to write to hlsl/default.hlsl\n");
1884 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1887 texturemode = GL_MODULATE;
1888 switch (vid.renderpath)
1890 case RENDERPATH_D3D9:
1892 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))));
1893 R_Mesh_TexBind(GL20TU_FIRST , first );
1894 R_Mesh_TexBind(GL20TU_SECOND, second);
1897 case RENDERPATH_D3D10:
1898 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1900 case RENDERPATH_D3D11:
1901 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1903 case RENDERPATH_GL20:
1904 case RENDERPATH_GLES2:
1905 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))));
1906 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1907 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1909 case RENDERPATH_GL13:
1910 R_Mesh_TexBind(0, first );
1911 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1912 R_Mesh_TexBind(1, second);
1914 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1916 case RENDERPATH_GL11:
1917 R_Mesh_TexBind(0, first );
1919 case RENDERPATH_SOFT:
1920 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))));
1921 R_Mesh_TexBind(GL20TU_FIRST , first );
1922 R_Mesh_TexBind(GL20TU_SECOND, second);
1927 void R_SetupShader_DepthOrShadow(void)
1929 switch (vid.renderpath)
1931 case RENDERPATH_D3D9:
1933 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1936 case RENDERPATH_D3D10:
1937 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1939 case RENDERPATH_D3D11:
1940 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1942 case RENDERPATH_GL20:
1943 case RENDERPATH_GLES2:
1944 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1946 case RENDERPATH_GL13:
1947 R_Mesh_TexBind(0, 0);
1948 R_Mesh_TexBind(1, 0);
1950 case RENDERPATH_GL11:
1951 R_Mesh_TexBind(0, 0);
1953 case RENDERPATH_SOFT:
1954 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1959 void R_SetupShader_ShowDepth(void)
1961 switch (vid.renderpath)
1963 case RENDERPATH_D3D9:
1965 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1968 case RENDERPATH_D3D10:
1969 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1971 case RENDERPATH_D3D11:
1972 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1974 case RENDERPATH_GL20:
1975 case RENDERPATH_GLES2:
1976 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1978 case RENDERPATH_GL13:
1980 case RENDERPATH_GL11:
1982 case RENDERPATH_SOFT:
1983 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
1988 extern qboolean r_shadow_usingdeferredprepass;
1989 extern cvar_t r_shadow_deferred_8bitrange;
1990 extern rtexture_t *r_shadow_attenuationgradienttexture;
1991 extern rtexture_t *r_shadow_attenuation2dtexture;
1992 extern rtexture_t *r_shadow_attenuation3dtexture;
1993 extern qboolean r_shadow_usingshadowmap2d;
1994 extern qboolean r_shadow_usingshadowmaportho;
1995 extern float r_shadow_shadowmap_texturescale[2];
1996 extern float r_shadow_shadowmap_parameters[4];
1997 extern qboolean r_shadow_shadowmapvsdct;
1998 extern qboolean r_shadow_shadowmapsampler;
1999 extern int r_shadow_shadowmappcf;
2000 extern rtexture_t *r_shadow_shadowmap2dtexture;
2001 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2002 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2003 extern matrix4x4_t r_shadow_shadowmapmatrix;
2004 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2005 extern int r_shadow_prepass_width;
2006 extern int r_shadow_prepass_height;
2007 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2008 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2009 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2010 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2011 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2013 #define BLENDFUNC_ALLOWS_COLORMOD 1
2014 #define BLENDFUNC_ALLOWS_FOG 2
2015 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2016 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2017 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2018 static int R_BlendFuncFlags(int src, int dst)
2022 // a blendfunc allows colormod if:
2023 // a) it can never keep the destination pixel invariant, or
2024 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2025 // this is to prevent unintended side effects from colormod
2027 // a blendfunc allows fog if:
2028 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2029 // this is to prevent unintended side effects from fog
2031 // these checks are the output of fogeval.pl
2033 r |= BLENDFUNC_ALLOWS_COLORMOD;
2034 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2035 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2036 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2037 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2038 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2039 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2040 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2041 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2042 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2043 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2044 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2045 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2046 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2047 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2048 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2049 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2050 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2051 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2052 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2053 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2054 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2059 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)
2061 // select a permutation of the lighting shader appropriate to this
2062 // combination of texture, entity, light source, and fogging, only use the
2063 // minimum features necessary to avoid wasting rendering time in the
2064 // fragment shader on features that are not being used
2065 unsigned int permutation = 0;
2066 unsigned int mode = 0;
2068 static float dummy_colormod[3] = {1, 1, 1};
2069 float *colormod = rsurface.colormod;
2071 matrix4x4_t tempmatrix;
2072 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2073 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2074 permutation |= SHADERPERMUTATION_ALPHAKILL;
2075 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2076 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2077 if (rsurfacepass == RSURFPASS_BACKGROUND)
2079 // distorted background
2080 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2082 mode = SHADERMODE_WATER;
2083 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2085 // this is the right thing to do for wateralpha
2086 GL_BlendFunc(GL_ONE, GL_ZERO);
2087 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2091 // this is the right thing to do for entity alpha
2092 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2093 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2096 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2098 mode = SHADERMODE_REFRACTION;
2099 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2100 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2104 mode = SHADERMODE_GENERIC;
2105 permutation |= SHADERPERMUTATION_DIFFUSE;
2106 GL_BlendFunc(GL_ONE, GL_ZERO);
2107 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2110 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2112 if (r_glsl_offsetmapping.integer)
2114 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2115 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2116 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2117 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2118 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2120 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2121 if (r_glsl_offsetmapping_reliefmapping.integer)
2122 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2125 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2126 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2127 // normalmap (deferred prepass), may use alpha test on diffuse
2128 mode = SHADERMODE_DEFERREDGEOMETRY;
2129 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2130 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2131 GL_BlendFunc(GL_ONE, GL_ZERO);
2132 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2134 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2136 if (r_glsl_offsetmapping.integer)
2138 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2139 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2140 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2141 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2142 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2144 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2145 if (r_glsl_offsetmapping_reliefmapping.integer)
2146 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2149 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2150 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2152 mode = SHADERMODE_LIGHTSOURCE;
2153 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2154 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2155 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2156 permutation |= SHADERPERMUTATION_CUBEFILTER;
2157 if (diffusescale > 0)
2158 permutation |= SHADERPERMUTATION_DIFFUSE;
2159 if (specularscale > 0)
2160 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2161 if (r_refdef.fogenabled)
2162 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2163 if (rsurface.texture->colormapping)
2164 permutation |= SHADERPERMUTATION_COLORMAPPING;
2165 if (r_shadow_usingshadowmap2d)
2167 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2168 if(r_shadow_shadowmapvsdct)
2169 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2171 if (r_shadow_shadowmapsampler)
2172 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2173 if (r_shadow_shadowmappcf > 1)
2174 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2175 else if (r_shadow_shadowmappcf)
2176 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2178 if (rsurface.texture->reflectmasktexture)
2179 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2180 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2181 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2183 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2185 if (r_glsl_offsetmapping.integer)
2187 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2188 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2189 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2190 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2191 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2193 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2194 if (r_glsl_offsetmapping_reliefmapping.integer)
2195 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2198 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2199 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2200 // unshaded geometry (fullbright or ambient model lighting)
2201 mode = SHADERMODE_FLATCOLOR;
2202 ambientscale = diffusescale = specularscale = 0;
2203 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2204 permutation |= SHADERPERMUTATION_GLOW;
2205 if (r_refdef.fogenabled)
2206 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2207 if (rsurface.texture->colormapping)
2208 permutation |= SHADERPERMUTATION_COLORMAPPING;
2209 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2211 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2212 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2214 if (r_shadow_shadowmapsampler)
2215 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2216 if (r_shadow_shadowmappcf > 1)
2217 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2218 else if (r_shadow_shadowmappcf)
2219 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2221 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2222 permutation |= SHADERPERMUTATION_REFLECTION;
2223 if (rsurface.texture->reflectmasktexture)
2224 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2225 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2226 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2228 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2230 if (r_glsl_offsetmapping.integer)
2232 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2233 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2234 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2235 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2236 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2238 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2239 if (r_glsl_offsetmapping_reliefmapping.integer)
2240 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2243 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2244 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2245 // directional model lighting
2246 mode = SHADERMODE_LIGHTDIRECTION;
2247 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2248 permutation |= SHADERPERMUTATION_GLOW;
2249 permutation |= SHADERPERMUTATION_DIFFUSE;
2250 if (specularscale > 0)
2251 permutation |= SHADERPERMUTATION_SPECULAR;
2252 if (r_refdef.fogenabled)
2253 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2254 if (rsurface.texture->colormapping)
2255 permutation |= SHADERPERMUTATION_COLORMAPPING;
2256 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2258 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2259 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2261 if (r_shadow_shadowmapsampler)
2262 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2263 if (r_shadow_shadowmappcf > 1)
2264 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2265 else if (r_shadow_shadowmappcf)
2266 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2268 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2269 permutation |= SHADERPERMUTATION_REFLECTION;
2270 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2271 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2272 if (rsurface.texture->reflectmasktexture)
2273 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2274 if (r_shadow_bouncegridtexture)
2276 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2277 if (r_shadow_bouncegriddirectional)
2278 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2280 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2281 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2283 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2285 if (r_glsl_offsetmapping.integer)
2287 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2288 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2289 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2290 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2291 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2293 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2294 if (r_glsl_offsetmapping_reliefmapping.integer)
2295 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2298 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2299 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2300 // ambient model lighting
2301 mode = SHADERMODE_LIGHTDIRECTION;
2302 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2303 permutation |= SHADERPERMUTATION_GLOW;
2304 if (r_refdef.fogenabled)
2305 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2306 if (rsurface.texture->colormapping)
2307 permutation |= SHADERPERMUTATION_COLORMAPPING;
2308 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2310 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2311 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2313 if (r_shadow_shadowmapsampler)
2314 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2315 if (r_shadow_shadowmappcf > 1)
2316 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2317 else if (r_shadow_shadowmappcf)
2318 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2320 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2321 permutation |= SHADERPERMUTATION_REFLECTION;
2322 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2323 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2324 if (rsurface.texture->reflectmasktexture)
2325 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2326 if (r_shadow_bouncegridtexture)
2328 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2329 if (r_shadow_bouncegriddirectional)
2330 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2332 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2333 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2337 if (r_glsl_offsetmapping.integer)
2339 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2340 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2341 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2342 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2343 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2345 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2346 if (r_glsl_offsetmapping_reliefmapping.integer)
2347 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2350 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2351 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2353 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2354 permutation |= SHADERPERMUTATION_GLOW;
2355 if (r_refdef.fogenabled)
2356 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2357 if (rsurface.texture->colormapping)
2358 permutation |= SHADERPERMUTATION_COLORMAPPING;
2359 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2361 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2362 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2364 if (r_shadow_shadowmapsampler)
2365 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2366 if (r_shadow_shadowmappcf > 1)
2367 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2368 else if (r_shadow_shadowmappcf)
2369 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2371 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2372 permutation |= SHADERPERMUTATION_REFLECTION;
2373 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2374 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2375 if (rsurface.texture->reflectmasktexture)
2376 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2377 if (FAKELIGHT_ENABLED)
2379 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2380 mode = SHADERMODE_FAKELIGHT;
2381 permutation |= SHADERPERMUTATION_DIFFUSE;
2382 if (specularscale > 0)
2383 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2385 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2387 // deluxemapping (light direction texture)
2388 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2389 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2391 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2392 permutation |= SHADERPERMUTATION_DIFFUSE;
2393 if (specularscale > 0)
2394 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2396 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2398 // fake deluxemapping (uniform light direction in tangentspace)
2399 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2400 permutation |= SHADERPERMUTATION_DIFFUSE;
2401 if (specularscale > 0)
2402 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2404 else if (rsurface.uselightmaptexture)
2406 // ordinary lightmapping (q1bsp, q3bsp)
2407 mode = SHADERMODE_LIGHTMAP;
2411 // ordinary vertex coloring (q3bsp)
2412 mode = SHADERMODE_VERTEXCOLOR;
2414 if (r_shadow_bouncegridtexture)
2416 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2417 if (r_shadow_bouncegriddirectional)
2418 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2420 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2421 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2423 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2424 colormod = dummy_colormod;
2425 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2426 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2427 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2428 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2429 switch(vid.renderpath)
2431 case RENDERPATH_D3D9:
2433 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);
2434 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2435 R_SetupShader_SetPermutationHLSL(mode, permutation);
2436 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2437 if (mode == SHADERMODE_LIGHTSOURCE)
2439 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2440 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2444 if (mode == SHADERMODE_LIGHTDIRECTION)
2446 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2449 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2450 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2451 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2452 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2453 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2455 if (mode == SHADERMODE_LIGHTSOURCE)
2457 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2458 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2459 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2460 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2461 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2463 // additive passes are only darkened by fog, not tinted
2464 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2465 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2469 if (mode == SHADERMODE_FLATCOLOR)
2471 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2473 else if (mode == SHADERMODE_LIGHTDIRECTION)
2475 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]);
2476 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2477 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);
2478 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);
2479 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2480 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2481 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2485 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2486 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2487 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2488 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2489 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2491 // additive passes are only darkened by fog, not tinted
2492 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2493 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2495 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2496 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);
2497 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2498 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2499 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2500 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2501 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2502 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2503 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2504 if (mode == SHADERMODE_WATER)
2505 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2507 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2508 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2509 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2510 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));
2511 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2512 if (rsurface.texture->pantstexture)
2513 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2515 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2516 if (rsurface.texture->shirttexture)
2517 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2519 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2520 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2521 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2522 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2523 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2524 hlslPSSetParameter3f(D3DPSREGISTER_OffsetMapping_ScaleSteps, r_glsl_offsetmapping_scale.value, max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer));
2525 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2526 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2528 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2529 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2530 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2531 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2532 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2533 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2534 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2535 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2536 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2537 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2538 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2539 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2540 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2541 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2542 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2543 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2544 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2545 if (rsurfacepass == RSURFPASS_BACKGROUND)
2547 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2548 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2549 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2553 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2555 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2556 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2557 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2558 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2559 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2561 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2562 if (rsurface.rtlight)
2564 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2565 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2570 case RENDERPATH_D3D10:
2571 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2573 case RENDERPATH_D3D11:
2574 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2576 case RENDERPATH_GL20:
2577 case RENDERPATH_GLES2:
2578 if (!vid.useinterleavedarrays)
2580 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);
2581 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2582 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2583 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2584 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2585 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2586 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2587 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2591 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);
2592 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2594 R_SetupShader_SetPermutationGLSL(mode, permutation);
2595 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2596 if (mode == SHADERMODE_LIGHTSOURCE)
2598 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2599 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2600 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2601 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2602 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2603 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);
2605 // additive passes are only darkened by fog, not tinted
2606 if (r_glsl_permutation->loc_FogColor >= 0)
2607 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2608 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2612 if (mode == SHADERMODE_FLATCOLOR)
2614 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2616 else if (mode == SHADERMODE_LIGHTDIRECTION)
2618 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]);
2619 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]);
2620 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);
2621 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);
2622 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);
2623 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]);
2624 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]);
2628 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]);
2629 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]);
2630 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2631 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2632 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2634 // additive passes are only darkened by fog, not tinted
2635 if (r_glsl_permutation->loc_FogColor >= 0)
2637 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2638 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2640 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2642 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);
2643 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]);
2644 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]);
2645 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]);
2646 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]);
2647 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2648 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2649 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2650 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]);
2652 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2653 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2654 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2655 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]);
2656 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]);
2658 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2659 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));
2660 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2661 if (r_glsl_permutation->loc_Color_Pants >= 0)
2663 if (rsurface.texture->pantstexture)
2664 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2666 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2668 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2670 if (rsurface.texture->shirttexture)
2671 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2673 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2675 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]);
2676 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2677 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2678 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2679 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform3f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale, max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer));
2680 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]);
2681 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2682 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);}
2683 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2685 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2686 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2687 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2688 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2689 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2690 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2691 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2692 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2693 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2694 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2695 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2696 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2697 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2698 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2699 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);
2700 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2701 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2702 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2703 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2704 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2705 if (rsurfacepass == RSURFPASS_BACKGROUND)
2707 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);
2708 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);
2709 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);
2713 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);
2715 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2716 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2717 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2718 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2719 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2721 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
2722 if (rsurface.rtlight)
2724 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2725 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2728 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2731 case RENDERPATH_GL13:
2732 case RENDERPATH_GL11:
2734 case RENDERPATH_SOFT:
2735 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);
2736 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2737 R_SetupShader_SetPermutationSoft(mode, permutation);
2738 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2739 if (mode == SHADERMODE_LIGHTSOURCE)
2741 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2742 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2743 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2744 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2745 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2746 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2748 // additive passes are only darkened by fog, not tinted
2749 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2750 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2754 if (mode == SHADERMODE_FLATCOLOR)
2756 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2758 else if (mode == SHADERMODE_LIGHTDIRECTION)
2760 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]);
2761 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2762 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);
2763 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);
2764 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2765 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]);
2766 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2770 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2771 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2772 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2773 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2774 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2776 // additive passes are only darkened by fog, not tinted
2777 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2778 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2780 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2781 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);
2782 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2783 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2784 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]);
2785 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]);
2786 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2787 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2788 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2789 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2791 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2792 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2793 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2794 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2795 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]);
2797 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2798 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));
2799 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2800 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2802 if (rsurface.texture->pantstexture)
2803 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2805 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2807 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2809 if (rsurface.texture->shirttexture)
2810 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2812 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2814 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2815 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2816 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2817 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2818 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale, max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer));
2819 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2820 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2822 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2823 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2824 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2825 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2826 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2827 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2828 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2829 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2830 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2831 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2832 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2833 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2834 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2835 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2836 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2837 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2838 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2839 if (rsurfacepass == RSURFPASS_BACKGROUND)
2841 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2842 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2843 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2847 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2849 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2850 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2851 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2852 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2853 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2855 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2856 if (rsurface.rtlight)
2858 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2859 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2866 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2868 // select a permutation of the lighting shader appropriate to this
2869 // combination of texture, entity, light source, and fogging, only use the
2870 // minimum features necessary to avoid wasting rendering time in the
2871 // fragment shader on features that are not being used
2872 unsigned int permutation = 0;
2873 unsigned int mode = 0;
2874 const float *lightcolorbase = rtlight->currentcolor;
2875 float ambientscale = rtlight->ambientscale;
2876 float diffusescale = rtlight->diffusescale;
2877 float specularscale = rtlight->specularscale;
2878 // this is the location of the light in view space
2879 vec3_t viewlightorigin;
2880 // this transforms from view space (camera) to light space (cubemap)
2881 matrix4x4_t viewtolight;
2882 matrix4x4_t lighttoview;
2883 float viewtolight16f[16];
2884 float range = 1.0f / r_shadow_deferred_8bitrange.value;
2886 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2887 if (rtlight->currentcubemap != r_texture_whitecube)
2888 permutation |= SHADERPERMUTATION_CUBEFILTER;
2889 if (diffusescale > 0)
2890 permutation |= SHADERPERMUTATION_DIFFUSE;
2891 if (specularscale > 0 && r_shadow_gloss.integer > 0)
2892 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2893 if (r_shadow_usingshadowmap2d)
2895 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2896 if (r_shadow_shadowmapvsdct)
2897 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2899 if (r_shadow_shadowmapsampler)
2900 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2901 if (r_shadow_shadowmappcf > 1)
2902 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2903 else if (r_shadow_shadowmappcf)
2904 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2906 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2907 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2908 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2909 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2910 switch(vid.renderpath)
2912 case RENDERPATH_D3D9:
2914 R_SetupShader_SetPermutationHLSL(mode, permutation);
2915 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2916 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2917 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2918 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2919 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2920 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2921 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2922 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2923 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2924 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2926 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2927 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
2928 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2929 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2930 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
2931 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2934 case RENDERPATH_D3D10:
2935 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2937 case RENDERPATH_D3D11:
2938 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2940 case RENDERPATH_GL20:
2941 case RENDERPATH_GLES2:
2942 R_SetupShader_SetPermutationGLSL(mode, permutation);
2943 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2944 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
2945 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);
2946 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);
2947 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);
2948 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]);
2949 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]);
2950 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));
2951 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]);
2952 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
2954 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2955 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2956 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2957 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2958 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
2959 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2961 case RENDERPATH_GL13:
2962 case RENDERPATH_GL11:
2964 case RENDERPATH_SOFT:
2965 R_SetupShader_SetPermutationGLSL(mode, permutation);
2966 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2967 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
2968 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2969 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2970 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2971 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2972 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]);
2973 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));
2974 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2975 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2977 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2978 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2979 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2980 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2981 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
2982 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2987 #define SKINFRAME_HASH 1024
2991 int loadsequence; // incremented each level change
2992 memexpandablearray_t array;
2993 skinframe_t *hash[SKINFRAME_HASH];
2996 r_skinframe_t r_skinframe;
2998 void R_SkinFrame_PrepareForPurge(void)
3000 r_skinframe.loadsequence++;
3001 // wrap it without hitting zero
3002 if (r_skinframe.loadsequence >= 200)
3003 r_skinframe.loadsequence = 1;
3006 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3010 // mark the skinframe as used for the purging code
3011 skinframe->loadsequence = r_skinframe.loadsequence;
3014 void R_SkinFrame_Purge(void)
3018 for (i = 0;i < SKINFRAME_HASH;i++)
3020 for (s = r_skinframe.hash[i];s;s = s->next)
3022 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3024 if (s->merged == s->base)
3026 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3027 R_PurgeTexture(s->stain );s->stain = NULL;
3028 R_PurgeTexture(s->merged);s->merged = NULL;
3029 R_PurgeTexture(s->base );s->base = NULL;
3030 R_PurgeTexture(s->pants );s->pants = NULL;
3031 R_PurgeTexture(s->shirt );s->shirt = NULL;
3032 R_PurgeTexture(s->nmap );s->nmap = NULL;
3033 R_PurgeTexture(s->gloss );s->gloss = NULL;
3034 R_PurgeTexture(s->glow );s->glow = NULL;
3035 R_PurgeTexture(s->fog );s->fog = NULL;
3036 R_PurgeTexture(s->reflect);s->reflect = NULL;
3037 s->loadsequence = 0;
3043 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3045 char basename[MAX_QPATH];
3047 Image_StripImageExtension(name, basename, sizeof(basename));
3049 if( last == NULL ) {
3051 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3052 item = r_skinframe.hash[hashindex];
3057 // linearly search through the hash bucket
3058 for( ; item ; item = item->next ) {
3059 if( !strcmp( item->basename, basename ) ) {
3066 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3070 char basename[MAX_QPATH];
3072 Image_StripImageExtension(name, basename, sizeof(basename));
3074 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3075 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3076 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3080 rtexture_t *dyntexture;
3081 // check whether its a dynamic texture
3082 dyntexture = CL_GetDynTexture( basename );
3083 if (!add && !dyntexture)
3085 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3086 memset(item, 0, sizeof(*item));
3087 strlcpy(item->basename, basename, sizeof(item->basename));
3088 item->base = dyntexture; // either NULL or dyntexture handle
3089 item->textureflags = textureflags;
3090 item->comparewidth = comparewidth;
3091 item->compareheight = compareheight;
3092 item->comparecrc = comparecrc;
3093 item->next = r_skinframe.hash[hashindex];
3094 r_skinframe.hash[hashindex] = item;
3096 else if( item->base == NULL )
3098 rtexture_t *dyntexture;
3099 // check whether its a dynamic texture
3100 // 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]
3101 dyntexture = CL_GetDynTexture( basename );
3102 item->base = dyntexture; // either NULL or dyntexture handle
3105 R_SkinFrame_MarkUsed(item);
3109 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3111 unsigned long long avgcolor[5], wsum; \
3119 for(pix = 0; pix < cnt; ++pix) \
3122 for(comp = 0; comp < 3; ++comp) \
3124 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3127 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3129 for(comp = 0; comp < 3; ++comp) \
3130 avgcolor[comp] += getpixel * w; \
3133 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3134 avgcolor[4] += getpixel; \
3136 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3138 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3139 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3140 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3141 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3144 extern cvar_t gl_picmip;
3145 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3148 unsigned char *pixels;
3149 unsigned char *bumppixels;
3150 unsigned char *basepixels = NULL;
3151 int basepixels_width = 0;
3152 int basepixels_height = 0;
3153 skinframe_t *skinframe;
3154 rtexture_t *ddsbase = NULL;
3155 qboolean ddshasalpha = false;
3156 float ddsavgcolor[4];
3157 char basename[MAX_QPATH];
3158 int miplevel = R_PicmipForFlags(textureflags);
3159 int savemiplevel = miplevel;
3162 if (cls.state == ca_dedicated)
3165 // return an existing skinframe if already loaded
3166 // if loading of the first image fails, don't make a new skinframe as it
3167 // would cause all future lookups of this to be missing
3168 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3169 if (skinframe && skinframe->base)
3172 Image_StripImageExtension(name, basename, sizeof(basename));
3174 // check for DDS texture file first
3175 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3177 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
3178 if (basepixels == NULL)
3182 // FIXME handle miplevel
3184 if (developer_loading.integer)
3185 Con_Printf("loading skin \"%s\"\n", name);
3187 // we've got some pixels to store, so really allocate this new texture now
3189 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3190 skinframe->stain = NULL;
3191 skinframe->merged = NULL;
3192 skinframe->base = NULL;
3193 skinframe->pants = NULL;
3194 skinframe->shirt = NULL;
3195 skinframe->nmap = NULL;
3196 skinframe->gloss = NULL;
3197 skinframe->glow = NULL;
3198 skinframe->fog = NULL;
3199 skinframe->reflect = NULL;
3200 skinframe->hasalpha = false;
3204 skinframe->base = ddsbase;
3205 skinframe->hasalpha = ddshasalpha;
3206 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3207 if (r_loadfog && skinframe->hasalpha)
3208 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3209 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3213 basepixels_width = image_width;
3214 basepixels_height = image_height;
3215 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);
3216 if (textureflags & TEXF_ALPHA)
3218 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3220 if (basepixels[j] < 255)
3222 skinframe->hasalpha = true;
3226 if (r_loadfog && skinframe->hasalpha)
3228 // has transparent pixels
3229 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3230 for (j = 0;j < image_width * image_height * 4;j += 4)
3235 pixels[j+3] = basepixels[j+3];
3237 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);
3241 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3242 //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]);
3243 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3244 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
3245 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3246 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
3251 mymiplevel = savemiplevel;
3252 if (r_loadnormalmap)
3253 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);
3254 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3256 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3257 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3258 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3259 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3262 // _norm is the name used by tenebrae and has been adopted as standard
3263 if (r_loadnormalmap && skinframe->nmap == NULL)
3265 mymiplevel = savemiplevel;
3266 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3268 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);
3272 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3274 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3275 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3276 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);
3278 Mem_Free(bumppixels);
3280 else if (r_shadow_bumpscale_basetexture.value > 0)
3282 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3283 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3284 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);
3287 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3288 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
3291 // _luma is supported only for tenebrae compatibility
3292 // _glow is the preferred name
3293 mymiplevel = savemiplevel;
3294 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))))
3296 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);
3297 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3298 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
3299 Mem_Free(pixels);pixels = NULL;
3302 mymiplevel = savemiplevel;
3303 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3305 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);
3306 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3307 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
3312 mymiplevel = savemiplevel;
3313 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3315 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);
3316 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3317 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
3322 mymiplevel = savemiplevel;
3323 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3325 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);
3326 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3327 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
3332 mymiplevel = savemiplevel;
3333 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3335 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);
3336 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3337 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
3343 Mem_Free(basepixels);
3348 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3349 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
3352 unsigned char *temp1, *temp2;
3353 skinframe_t *skinframe;
3355 if (cls.state == ca_dedicated)
3358 // if already loaded just return it, otherwise make a new skinframe
3359 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3360 if (skinframe && skinframe->base)
3363 skinframe->stain = NULL;
3364 skinframe->merged = NULL;
3365 skinframe->base = NULL;
3366 skinframe->pants = NULL;
3367 skinframe->shirt = NULL;
3368 skinframe->nmap = NULL;
3369 skinframe->gloss = NULL;
3370 skinframe->glow = NULL;
3371 skinframe->fog = NULL;
3372 skinframe->reflect = NULL;
3373 skinframe->hasalpha = false;
3375 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3379 if (developer_loading.integer)
3380 Con_Printf("loading 32bit skin \"%s\"\n", name);
3382 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3384 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3385 temp2 = temp1 + width * height * 4;
3386 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3387 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);
3390 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
3391 if (textureflags & TEXF_ALPHA)
3393 for (i = 3;i < width * height * 4;i += 4)
3395 if (skindata[i] < 255)
3397 skinframe->hasalpha = true;
3401 if (r_loadfog && skinframe->hasalpha)
3403 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3404 memcpy(fogpixels, skindata, width * height * 4);
3405 for (i = 0;i < width * height * 4;i += 4)
3406 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3407 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3408 Mem_Free(fogpixels);
3412 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3413 //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]);
3418 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3422 skinframe_t *skinframe;
3424 if (cls.state == ca_dedicated)
3427 // if already loaded just return it, otherwise make a new skinframe
3428 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3429 if (skinframe && skinframe->base)
3432 skinframe->stain = NULL;
3433 skinframe->merged = NULL;
3434 skinframe->base = NULL;
3435 skinframe->pants = NULL;
3436 skinframe->shirt = NULL;
3437 skinframe->nmap = NULL;
3438 skinframe->gloss = NULL;
3439 skinframe->glow = NULL;
3440 skinframe->fog = NULL;
3441 skinframe->reflect = NULL;
3442 skinframe->hasalpha = false;
3444 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3448 if (developer_loading.integer)
3449 Con_Printf("loading quake skin \"%s\"\n", name);
3451 // 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)
3452 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3453 memcpy(skinframe->qpixels, skindata, width*height);
3454 skinframe->qwidth = width;
3455 skinframe->qheight = height;
3458 for (i = 0;i < width * height;i++)
3459 featuresmask |= palette_featureflags[skindata[i]];
3461 skinframe->hasalpha = false;
3462 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3463 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3464 skinframe->qgeneratemerged = true;
3465 skinframe->qgeneratebase = skinframe->qhascolormapping;
3466 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3468 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3469 //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]);
3474 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3478 unsigned char *skindata;
3480 if (!skinframe->qpixels)
3483 if (!skinframe->qhascolormapping)
3484 colormapped = false;
3488 if (!skinframe->qgeneratebase)
3493 if (!skinframe->qgeneratemerged)
3497 width = skinframe->qwidth;
3498 height = skinframe->qheight;
3499 skindata = skinframe->qpixels;
3501 if (skinframe->qgeneratenmap)
3503 unsigned char *temp1, *temp2;
3504 skinframe->qgeneratenmap = false;
3505 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3506 temp2 = temp1 + width * height * 4;
3507 // use either a custom palette or the quake palette
3508 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3509 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3510 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);
3514 if (skinframe->qgenerateglow)
3516 skinframe->qgenerateglow = false;
3517 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3522 skinframe->qgeneratebase = false;
3523 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);
3524 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3525 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3529 skinframe->qgeneratemerged = false;
3530 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);
3533 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3535 Mem_Free(skinframe->qpixels);
3536 skinframe->qpixels = NULL;
3540 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)
3543 skinframe_t *skinframe;
3545 if (cls.state == ca_dedicated)
3548 // if already loaded just return it, otherwise make a new skinframe
3549 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3550 if (skinframe && skinframe->base)
3553 skinframe->stain = NULL;
3554 skinframe->merged = NULL;
3555 skinframe->base = NULL;
3556 skinframe->pants = NULL;
3557 skinframe->shirt = NULL;
3558 skinframe->nmap = NULL;
3559 skinframe->gloss = NULL;
3560 skinframe->glow = NULL;
3561 skinframe->fog = NULL;
3562 skinframe->reflect = NULL;
3563 skinframe->hasalpha = false;
3565 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3569 if (developer_loading.integer)
3570 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3572 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3573 if (textureflags & TEXF_ALPHA)
3575 for (i = 0;i < width * height;i++)
3577 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3579 skinframe->hasalpha = true;
3583 if (r_loadfog && skinframe->hasalpha)
3584 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3587 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3588 //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]);
3593 skinframe_t *R_SkinFrame_LoadMissing(void)
3595 skinframe_t *skinframe;
3597 if (cls.state == ca_dedicated)
3600 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3601 skinframe->stain = NULL;
3602 skinframe->merged = NULL;
3603 skinframe->base = NULL;
3604 skinframe->pants = NULL;
3605 skinframe->shirt = NULL;
3606 skinframe->nmap = NULL;
3607 skinframe->gloss = NULL;
3608 skinframe->glow = NULL;
3609 skinframe->fog = NULL;
3610 skinframe->reflect = NULL;
3611 skinframe->hasalpha = false;
3613 skinframe->avgcolor[0] = rand() / RAND_MAX;
3614 skinframe->avgcolor[1] = rand() / RAND_MAX;
3615 skinframe->avgcolor[2] = rand() / RAND_MAX;
3616 skinframe->avgcolor[3] = 1;
3621 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3622 typedef struct suffixinfo_s
3625 qboolean flipx, flipy, flipdiagonal;
3628 static suffixinfo_t suffix[3][6] =
3631 {"px", false, false, false},
3632 {"nx", false, false, false},
3633 {"py", false, false, false},
3634 {"ny", false, false, false},
3635 {"pz", false, false, false},
3636 {"nz", false, false, false}
3639 {"posx", false, false, false},
3640 {"negx", false, false, false},
3641 {"posy", false, false, false},
3642 {"negy", false, false, false},
3643 {"posz", false, false, false},
3644 {"negz", false, false, false}
3647 {"rt", true, false, true},
3648 {"lf", false, true, true},
3649 {"ft", true, true, false},
3650 {"bk", false, false, false},
3651 {"up", true, false, true},
3652 {"dn", true, false, true}
3656 static int componentorder[4] = {0, 1, 2, 3};
3658 rtexture_t *R_LoadCubemap(const char *basename)
3660 int i, j, cubemapsize;
3661 unsigned char *cubemappixels, *image_buffer;
3662 rtexture_t *cubemaptexture;
3664 // must start 0 so the first loadimagepixels has no requested width/height
3666 cubemappixels = NULL;
3667 cubemaptexture = NULL;
3668 // keep trying different suffix groups (posx, px, rt) until one loads
3669 for (j = 0;j < 3 && !cubemappixels;j++)
3671 // load the 6 images in the suffix group
3672 for (i = 0;i < 6;i++)
3674 // generate an image name based on the base and and suffix
3675 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3677 if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
3679 // an image loaded, make sure width and height are equal
3680 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3682 // if this is the first image to load successfully, allocate the cubemap memory
3683 if (!cubemappixels && image_width >= 1)
3685 cubemapsize = image_width;
3686 // note this clears to black, so unavailable sides are black
3687 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3689 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3691 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);
3694 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3696 Mem_Free(image_buffer);
3700 // if a cubemap loaded, upload it
3703 if (developer_loading.integer)
3704 Con_Printf("loading cubemap \"%s\"\n", basename);
3706 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3707 Mem_Free(cubemappixels);
3711 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3712 if (developer_loading.integer)
3714 Con_Printf("(tried tried images ");
3715 for (j = 0;j < 3;j++)
3716 for (i = 0;i < 6;i++)
3717 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3718 Con_Print(" and was unable to find any of them).\n");
3721 return cubemaptexture;
3724 rtexture_t *R_GetCubemap(const char *basename)
3727 for (i = 0;i < r_texture_numcubemaps;i++)
3728 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3729 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3730 if (i >= MAX_CUBEMAPS)
3731 return r_texture_whitecube;
3732 r_texture_numcubemaps++;
3733 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3734 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3735 return r_texture_cubemaps[i].texture;
3738 void R_FreeCubemaps(void)
3741 for (i = 0;i < r_texture_numcubemaps;i++)
3743 if (developer_loading.integer)
3744 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3745 if (r_texture_cubemaps[i].texture)
3746 R_FreeTexture(r_texture_cubemaps[i].texture);
3748 r_texture_numcubemaps = 0;
3751 void R_Main_FreeViewCache(void)
3753 if (r_refdef.viewcache.entityvisible)
3754 Mem_Free(r_refdef.viewcache.entityvisible);
3755 if (r_refdef.viewcache.world_pvsbits)
3756 Mem_Free(r_refdef.viewcache.world_pvsbits);
3757 if (r_refdef.viewcache.world_leafvisible)
3758 Mem_Free(r_refdef.viewcache.world_leafvisible);
3759 if (r_refdef.viewcache.world_surfacevisible)
3760 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3761 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3764 void R_Main_ResizeViewCache(void)
3766 int numentities = r_refdef.scene.numentities;
3767 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3768 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3769 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3770 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3771 if (r_refdef.viewcache.maxentities < numentities)
3773 r_refdef.viewcache.maxentities = numentities;
3774 if (r_refdef.viewcache.entityvisible)
3775 Mem_Free(r_refdef.viewcache.entityvisible);
3776 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3778 if (r_refdef.viewcache.world_numclusters != numclusters)
3780 r_refdef.viewcache.world_numclusters = numclusters;
3781 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3782 if (r_refdef.viewcache.world_pvsbits)
3783 Mem_Free(r_refdef.viewcache.world_pvsbits);
3784 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3786 if (r_refdef.viewcache.world_numleafs != numleafs)
3788 r_refdef.viewcache.world_numleafs = numleafs;
3789 if (r_refdef.viewcache.world_leafvisible)
3790 Mem_Free(r_refdef.viewcache.world_leafvisible);
3791 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3793 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3795 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3796 if (r_refdef.viewcache.world_surfacevisible)
3797 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3798 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3802 extern rtexture_t *loadingscreentexture;
3803 void gl_main_start(void)
3805 loadingscreentexture = NULL;
3806 r_texture_blanknormalmap = NULL;
3807 r_texture_white = NULL;
3808 r_texture_grey128 = NULL;
3809 r_texture_black = NULL;
3810 r_texture_whitecube = NULL;
3811 r_texture_normalizationcube = NULL;
3812 r_texture_fogattenuation = NULL;
3813 r_texture_fogheighttexture = NULL;
3814 r_texture_gammaramps = NULL;
3815 r_texture_numcubemaps = 0;
3817 r_loaddds = r_texture_dds_load.integer != 0;
3818 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3820 switch(vid.renderpath)
3822 case RENDERPATH_GL20:
3823 case RENDERPATH_D3D9:
3824 case RENDERPATH_D3D10:
3825 case RENDERPATH_D3D11:
3826 case RENDERPATH_SOFT:
3827 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3828 Cvar_SetValueQuick(&gl_combine, 1);
3829 Cvar_SetValueQuick(&r_glsl, 1);
3830 r_loadnormalmap = true;
3834 case RENDERPATH_GL13:
3835 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3836 Cvar_SetValueQuick(&gl_combine, 1);
3837 Cvar_SetValueQuick(&r_glsl, 0);
3838 r_loadnormalmap = false;
3839 r_loadgloss = false;
3842 case RENDERPATH_GL11:
3843 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3844 Cvar_SetValueQuick(&gl_combine, 0);
3845 Cvar_SetValueQuick(&r_glsl, 0);
3846 r_loadnormalmap = false;
3847 r_loadgloss = false;
3850 case RENDERPATH_GLES2:
3851 Cvar_SetValueQuick(&r_textureunits, 1);
3852 Cvar_SetValueQuick(&gl_combine, 1);
3853 Cvar_SetValueQuick(&r_glsl, 1);
3854 r_loadnormalmap = true;
3855 r_loadgloss = false;
3861 R_FrameData_Reset();
3865 memset(r_queries, 0, sizeof(r_queries));
3867 r_qwskincache = NULL;
3868 r_qwskincache_size = 0;
3870 // due to caching of texture_t references, the collision cache must be reset
3871 Collision_Cache_Reset(true);
3873 // set up r_skinframe loading system for textures
3874 memset(&r_skinframe, 0, sizeof(r_skinframe));
3875 r_skinframe.loadsequence = 1;
3876 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3878 r_main_texturepool = R_AllocTexturePool();
3879 R_BuildBlankTextures();
3881 if (vid.support.arb_texture_cube_map)
3884 R_BuildNormalizationCube();
3886 r_texture_fogattenuation = NULL;
3887 r_texture_fogheighttexture = NULL;
3888 r_texture_gammaramps = NULL;
3889 //r_texture_fogintensity = NULL;
3890 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3891 memset(&r_waterstate, 0, sizeof(r_waterstate));
3892 r_glsl_permutation = NULL;
3893 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3894 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3895 glslshaderstring = NULL;
3897 r_hlsl_permutation = NULL;
3898 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3899 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3901 hlslshaderstring = NULL;
3902 memset(&r_svbsp, 0, sizeof (r_svbsp));
3904 r_refdef.fogmasktable_density = 0;
3907 void gl_main_shutdown(void)
3910 R_FrameData_Reset();
3912 R_Main_FreeViewCache();
3914 switch(vid.renderpath)
3916 case RENDERPATH_GL11:
3917 case RENDERPATH_GL13:
3918 case RENDERPATH_GL20:
3919 case RENDERPATH_GLES2:
3921 qglDeleteQueriesARB(r_maxqueries, r_queries);
3923 case RENDERPATH_D3D9:
3924 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3926 case RENDERPATH_D3D10:
3927 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3929 case RENDERPATH_D3D11:
3930 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3932 case RENDERPATH_SOFT:
3938 memset(r_queries, 0, sizeof(r_queries));
3940 r_qwskincache = NULL;
3941 r_qwskincache_size = 0;
3943 // clear out the r_skinframe state
3944 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3945 memset(&r_skinframe, 0, sizeof(r_skinframe));
3948 Mem_Free(r_svbsp.nodes);
3949 memset(&r_svbsp, 0, sizeof (r_svbsp));
3950 R_FreeTexturePool(&r_main_texturepool);
3951 loadingscreentexture = NULL;
3952 r_texture_blanknormalmap = NULL;
3953 r_texture_white = NULL;
3954 r_texture_grey128 = NULL;
3955 r_texture_black = NULL;
3956 r_texture_whitecube = NULL;
3957 r_texture_normalizationcube = NULL;
3958 r_texture_fogattenuation = NULL;
3959 r_texture_fogheighttexture = NULL;
3960 r_texture_gammaramps = NULL;
3961 r_texture_numcubemaps = 0;
3962 //r_texture_fogintensity = NULL;
3963 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3964 memset(&r_waterstate, 0, sizeof(r_waterstate));
3967 r_glsl_permutation = NULL;
3968 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3969 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3970 glslshaderstring = NULL;
3972 r_hlsl_permutation = NULL;
3973 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3974 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3976 hlslshaderstring = NULL;
3979 extern void CL_ParseEntityLump(char *entitystring);
3980 void gl_main_newmap(void)
3982 // FIXME: move this code to client
3983 char *entities, entname[MAX_QPATH];
3985 Mem_Free(r_qwskincache);
3986 r_qwskincache = NULL;
3987 r_qwskincache_size = 0;
3990 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
3991 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
3993 CL_ParseEntityLump(entities);
3997 if (cl.worldmodel->brush.entities)
3998 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4000 R_Main_FreeViewCache();
4002 R_FrameData_Reset();
4005 void GL_Main_Init(void)
4007 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4009 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4010 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4011 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4012 if (gamemode == GAME_NEHAHRA)
4014 Cvar_RegisterVariable (&gl_fogenable);
4015 Cvar_RegisterVariable (&gl_fogdensity);
4016 Cvar_RegisterVariable (&gl_fogred);
4017 Cvar_RegisterVariable (&gl_foggreen);
4018 Cvar_RegisterVariable (&gl_fogblue);
4019 Cvar_RegisterVariable (&gl_fogstart);
4020 Cvar_RegisterVariable (&gl_fogend);
4021 Cvar_RegisterVariable (&gl_skyclip);
4023 Cvar_RegisterVariable(&r_motionblur);
4024 Cvar_RegisterVariable(&r_motionblur_maxblur);
4025 Cvar_RegisterVariable(&r_motionblur_bmin);
4026 Cvar_RegisterVariable(&r_motionblur_vmin);
4027 Cvar_RegisterVariable(&r_motionblur_vmax);
4028 Cvar_RegisterVariable(&r_motionblur_vcoeff);
4029 Cvar_RegisterVariable(&r_motionblur_randomize);
4030 Cvar_RegisterVariable(&r_damageblur);
4031 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4032 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4033 Cvar_RegisterVariable(&r_equalize_entities_by);
4034 Cvar_RegisterVariable(&r_equalize_entities_to);
4035 Cvar_RegisterVariable(&r_depthfirst);
4036 Cvar_RegisterVariable(&r_useinfinitefarclip);
4037 Cvar_RegisterVariable(&r_farclip_base);
4038 Cvar_RegisterVariable(&r_farclip_world);
4039 Cvar_RegisterVariable(&r_nearclip);
4040 Cvar_RegisterVariable(&r_showbboxes);
4041 Cvar_RegisterVariable(&r_showsurfaces);
4042 Cvar_RegisterVariable(&r_showtris);
4043 Cvar_RegisterVariable(&r_shownormals);
4044 Cvar_RegisterVariable(&r_showlighting);
4045 Cvar_RegisterVariable(&r_showshadowvolumes);
4046 Cvar_RegisterVariable(&r_showcollisionbrushes);
4047 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4048 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4049 Cvar_RegisterVariable(&r_showdisabledepthtest);
4050 Cvar_RegisterVariable(&r_drawportals);
4051 Cvar_RegisterVariable(&r_drawentities);
4052 Cvar_RegisterVariable(&r_draw2d);
4053 Cvar_RegisterVariable(&r_drawworld);
4054 Cvar_RegisterVariable(&r_cullentities_trace);
4055 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4056 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4057 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4058 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4059 Cvar_RegisterVariable(&r_drawviewmodel);
4060 Cvar_RegisterVariable(&r_drawexteriormodel);
4061 Cvar_RegisterVariable(&r_speeds);
4062 Cvar_RegisterVariable(&r_fullbrights);
4063 Cvar_RegisterVariable(&r_wateralpha);
4064 Cvar_RegisterVariable(&r_dynamic);
4065 Cvar_RegisterVariable(&r_fakelight);
4066 Cvar_RegisterVariable(&r_fakelight_intensity);
4067 Cvar_RegisterVariable(&r_fullbright);
4068 Cvar_RegisterVariable(&r_shadows);
4069 Cvar_RegisterVariable(&r_shadows_darken);
4070 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4071 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4072 Cvar_RegisterVariable(&r_shadows_throwdistance);
4073 Cvar_RegisterVariable(&r_shadows_throwdirection);
4074 Cvar_RegisterVariable(&r_shadows_focus);
4075 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4076 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4077 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4078 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4079 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4080 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4081 Cvar_RegisterVariable(&r_fog_exp2);
4082 Cvar_RegisterVariable(&r_fog_clear);
4083 Cvar_RegisterVariable(&r_drawfog);
4084 Cvar_RegisterVariable(&r_transparentdepthmasking);
4085 Cvar_RegisterVariable(&r_texture_dds_load);
4086 Cvar_RegisterVariable(&r_texture_dds_save);
4087 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
4088 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
4089 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
4090 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
4091 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
4092 Cvar_RegisterVariable(&r_textureunits);
4093 Cvar_RegisterVariable(&gl_combine);
4094 Cvar_RegisterVariable(&r_glsl);
4095 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4096 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4097 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4098 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4099 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4100 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4101 Cvar_RegisterVariable(&r_glsl_postprocess);
4102 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4103 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4104 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4105 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4106 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4107 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4108 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4109 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4111 Cvar_RegisterVariable(&r_water);
4112 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4113 Cvar_RegisterVariable(&r_water_clippingplanebias);
4114 Cvar_RegisterVariable(&r_water_refractdistort);
4115 Cvar_RegisterVariable(&r_water_reflectdistort);
4116 Cvar_RegisterVariable(&r_water_scissormode);
4117 Cvar_RegisterVariable(&r_lerpsprites);
4118 Cvar_RegisterVariable(&r_lerpmodels);
4119 Cvar_RegisterVariable(&r_lerplightstyles);
4120 Cvar_RegisterVariable(&r_waterscroll);
4121 Cvar_RegisterVariable(&r_bloom);
4122 Cvar_RegisterVariable(&r_bloom_colorscale);
4123 Cvar_RegisterVariable(&r_bloom_brighten);
4124 Cvar_RegisterVariable(&r_bloom_blur);
4125 Cvar_RegisterVariable(&r_bloom_resolution);
4126 Cvar_RegisterVariable(&r_bloom_colorexponent);
4127 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4128 Cvar_RegisterVariable(&r_hdr);
4129 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4130 Cvar_RegisterVariable(&r_hdr_glowintensity);
4131 Cvar_RegisterVariable(&r_hdr_range);
4132 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4133 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4134 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4135 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4136 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4137 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4138 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4139 Cvar_RegisterVariable(&developer_texturelogging);
4140 Cvar_RegisterVariable(&gl_lightmaps);
4141 Cvar_RegisterVariable(&r_test);
4142 Cvar_RegisterVariable(&r_glsl_saturation);
4143 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4144 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4145 Cvar_RegisterVariable(&r_framedatasize);
4146 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4147 Cvar_SetValue("r_fullbrights", 0);
4148 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4150 Cvar_RegisterVariable(&r_track_sprites);
4151 Cvar_RegisterVariable(&r_track_sprites_flags);
4152 Cvar_RegisterVariable(&r_track_sprites_scalew);
4153 Cvar_RegisterVariable(&r_track_sprites_scaleh);
4154 Cvar_RegisterVariable(&r_overheadsprites_perspective);
4155 Cvar_RegisterVariable(&r_overheadsprites_pushback);
4156 Cvar_RegisterVariable(&r_overheadsprites_scalex);
4157 Cvar_RegisterVariable(&r_overheadsprites_scaley);
4160 extern void R_Textures_Init(void);
4161 extern void GL_Draw_Init(void);
4162 extern void GL_Main_Init(void);
4163 extern void R_Shadow_Init(void);
4164 extern void R_Sky_Init(void);
4165 extern void GL_Surf_Init(void);
4166 extern void R_Particles_Init(void);
4167 extern void R_Explosion_Init(void);
4168 extern void gl_backend_init(void);
4169 extern void Sbar_Init(void);
4170 extern void R_LightningBeams_Init(void);
4171 extern void Mod_RenderInit(void);
4172 extern void Font_Init(void);
4174 void Render_Init(void)
4187 R_LightningBeams_Init();
4196 extern char *ENGINE_EXTENSIONS;
4199 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4200 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4201 gl_version = (const char *)qglGetString(GL_VERSION);
4202 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4206 if (!gl_platformextensions)
4207 gl_platformextensions = "";
4209 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4210 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4211 Con_Printf("GL_VERSION: %s\n", gl_version);
4212 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4213 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4215 VID_CheckExtensions();
4217 // LordHavoc: report supported extensions
4218 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4220 // clear to black (loading plaque will be seen over this)
4221 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4224 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4228 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4230 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4233 p = r_refdef.view.frustum + i;
4238 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4242 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4246 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4250 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4254 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4258 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4262 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4266 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4274 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4278 for (i = 0;i < numplanes;i++)
4285 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4289 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4293 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4297 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4301 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4305 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4309 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4313 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4321 //==================================================================================
4323 // LordHavoc: this stores temporary data used within the same frame
4325 typedef struct r_framedata_mem_s
4327 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4328 size_t size; // how much usable space
4329 size_t current; // how much space in use
4330 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4331 size_t wantedsize; // how much space was allocated
4332 unsigned char *data; // start of real data (16byte aligned)
4336 static r_framedata_mem_t *r_framedata_mem;
4338 void R_FrameData_Reset(void)
4340 while (r_framedata_mem)
4342 r_framedata_mem_t *next = r_framedata_mem->purge;
4343 Mem_Free(r_framedata_mem);
4344 r_framedata_mem = next;
4348 void R_FrameData_Resize(void)
4351 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4352 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4353 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4355 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4356 newmem->wantedsize = wantedsize;
4357 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4358 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4359 newmem->current = 0;
4361 newmem->purge = r_framedata_mem;
4362 r_framedata_mem = newmem;
4366 void R_FrameData_NewFrame(void)
4368 R_FrameData_Resize();
4369 if (!r_framedata_mem)
4371 // if we ran out of space on the last frame, free the old memory now
4372 while (r_framedata_mem->purge)
4374 // repeatedly remove the second item in the list, leaving only head
4375 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4376 Mem_Free(r_framedata_mem->purge);
4377 r_framedata_mem->purge = next;
4379 // reset the current mem pointer
4380 r_framedata_mem->current = 0;
4381 r_framedata_mem->mark = 0;
4384 void *R_FrameData_Alloc(size_t size)
4388 // align to 16 byte boundary - the data pointer is already aligned, so we
4389 // only need to ensure the size of every allocation is also aligned
4390 size = (size + 15) & ~15;
4392 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4394 // emergency - we ran out of space, allocate more memory
4395 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4396 R_FrameData_Resize();
4399 data = r_framedata_mem->data + r_framedata_mem->current;
4400 r_framedata_mem->current += size;
4402 // count the usage for stats
4403 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4404 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4406 return (void *)data;
4409 void *R_FrameData_Store(size_t size, void *data)
4411 void *d = R_FrameData_Alloc(size);
4413 memcpy(d, data, size);
4417 void R_FrameData_SetMark(void)
4419 if (!r_framedata_mem)
4421 r_framedata_mem->mark = r_framedata_mem->current;
4424 void R_FrameData_ReturnToMark(void)
4426 if (!r_framedata_mem)
4428 r_framedata_mem->current = r_framedata_mem->mark;
4431 //==================================================================================
4433 // LordHavoc: animcache originally written by Echon, rewritten since then
4436 * Animation cache prevents re-generating mesh data for an animated model
4437 * multiple times in one frame for lighting, shadowing, reflections, etc.
4440 void R_AnimCache_Free(void)
4444 void R_AnimCache_ClearCache(void)
4447 entity_render_t *ent;
4449 for (i = 0;i < r_refdef.scene.numentities;i++)
4451 ent = r_refdef.scene.entities[i];
4452 ent->animcache_vertex3f = NULL;
4453 ent->animcache_normal3f = NULL;
4454 ent->animcache_svector3f = NULL;
4455 ent->animcache_tvector3f = NULL;
4456 ent->animcache_vertexmesh = NULL;
4457 ent->animcache_vertex3fbuffer = NULL;
4458 ent->animcache_vertexmeshbuffer = NULL;
4462 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4466 // check if we need the meshbuffers
4467 if (!vid.useinterleavedarrays)
4470 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4471 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4472 // TODO: upload vertex3f buffer?
4473 if (ent->animcache_vertexmesh)
4475 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4476 for (i = 0;i < numvertices;i++)
4477 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4478 if (ent->animcache_svector3f)
4479 for (i = 0;i < numvertices;i++)
4480 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4481 if (ent->animcache_tvector3f)
4482 for (i = 0;i < numvertices;i++)
4483 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4484 if (ent->animcache_normal3f)
4485 for (i = 0;i < numvertices;i++)
4486 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4487 // TODO: upload vertexmeshbuffer?
4491 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4493 dp_model_t *model = ent->model;
4495 // see if it's already cached this frame
4496 if (ent->animcache_vertex3f)
4498 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4499 if (wantnormals || wanttangents)
4501 if (ent->animcache_normal3f)
4502 wantnormals = false;
4503 if (ent->animcache_svector3f)
4504 wanttangents = false;
4505 if (wantnormals || wanttangents)
4507 numvertices = model->surfmesh.num_vertices;
4509 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4512 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4513 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4515 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4516 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4522 // see if this ent is worth caching
4523 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4525 // get some memory for this entity and generate mesh data
4526 numvertices = model->surfmesh.num_vertices;
4527 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4529 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4532 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4533 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4535 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4536 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4541 void R_AnimCache_CacheVisibleEntities(void)
4544 qboolean wantnormals = true;
4545 qboolean wanttangents = !r_showsurfaces.integer;
4547 switch(vid.renderpath)
4549 case RENDERPATH_GL20:
4550 case RENDERPATH_D3D9:
4551 case RENDERPATH_D3D10:
4552 case RENDERPATH_D3D11:
4553 case RENDERPATH_GLES2:
4555 case RENDERPATH_GL13:
4556 case RENDERPATH_GL11:
4557 wanttangents = false;
4559 case RENDERPATH_SOFT:
4563 if (r_shownormals.integer)
4564 wanttangents = wantnormals = true;
4566 // TODO: thread this
4567 // NOTE: R_PrepareRTLights() also caches entities
4569 for (i = 0;i < r_refdef.scene.numentities;i++)
4570 if (r_refdef.viewcache.entityvisible[i])
4571 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4574 //==================================================================================
4576 static void R_View_UpdateEntityLighting (void)
4579 entity_render_t *ent;
4580 vec3_t tempdiffusenormal, avg;
4581 vec_t f, fa, fd, fdd;
4582 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4584 for (i = 0;i < r_refdef.scene.numentities;i++)
4586 ent = r_refdef.scene.entities[i];
4588 // skip unseen models
4589 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4593 if (ent->model && ent->model->brush.num_leafs)
4595 // TODO: use modellight for r_ambient settings on world?
4596 VectorSet(ent->modellight_ambient, 0, 0, 0);
4597 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4598 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4602 // fetch the lighting from the worldmodel data
4603 VectorClear(ent->modellight_ambient);
4604 VectorClear(ent->modellight_diffuse);
4605 VectorClear(tempdiffusenormal);
4606 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4609 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4611 // complete lightning for lit sprites
4612 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4613 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4615 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4616 org[2] = org[2] + r_overheadsprites_pushback.value;
4617 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4620 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4622 if(ent->flags & RENDER_EQUALIZE)
4624 // first fix up ambient lighting...
4625 if(r_equalize_entities_minambient.value > 0)
4627 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4630 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4631 if(fa < r_equalize_entities_minambient.value * fd)
4634 // fa'/fd' = minambient
4635 // fa'+0.25*fd' = fa+0.25*fd
4637 // fa' = fd' * minambient
4638 // fd'*(0.25+minambient) = fa+0.25*fd
4640 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4641 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4643 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4644 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
4645 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4646 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4651 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4653 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4654 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4658 // adjust brightness and saturation to target
4659 avg[0] = avg[1] = avg[2] = fa / f;
4660 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4661 avg[0] = avg[1] = avg[2] = fd / f;
4662 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4668 VectorSet(ent->modellight_ambient, 1, 1, 1);
4670 // move the light direction into modelspace coordinates for lighting code
4671 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4672 if(VectorLength2(ent->modellight_lightdir) == 0)
4673 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4674 VectorNormalize(ent->modellight_lightdir);
4678 #define MAX_LINEOFSIGHTTRACES 64
4680 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4683 vec3_t boxmins, boxmaxs;
4686 dp_model_t *model = r_refdef.scene.worldmodel;
4688 if (!model || !model->brush.TraceLineOfSight)
4691 // expand the box a little
4692 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4693 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4694 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4695 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4696 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4697 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4699 // return true if eye is inside enlarged box
4700 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4704 VectorCopy(eye, start);
4705 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4706 if (model->brush.TraceLineOfSight(model, start, end))
4709 // try various random positions
4710 for (i = 0;i < numsamples;i++)
4712 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4713 if (model->brush.TraceLineOfSight(model, start, end))
4721 static void R_View_UpdateEntityVisible (void)
4726 entity_render_t *ent;
4728 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4729 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4730 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
4731 : RENDER_EXTERIORMODEL;
4732 if (!r_drawviewmodel.integer)
4733 renderimask |= RENDER_VIEWMODEL;
4734 if (!r_drawexteriormodel.integer)
4735 renderimask |= RENDER_EXTERIORMODEL;
4736 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4738 // worldmodel can check visibility
4739 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4740 for (i = 0;i < r_refdef.scene.numentities;i++)
4742 ent = r_refdef.scene.entities[i];
4743 if (!(ent->flags & renderimask))
4744 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)))
4745 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))
4746 r_refdef.viewcache.entityvisible[i] = true;
4748 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4749 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4751 for (i = 0;i < r_refdef.scene.numentities;i++)
4753 ent = r_refdef.scene.entities[i];
4754 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4756 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4758 continue; // temp entities do pvs only
4759 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4760 ent->last_trace_visibility = realtime;
4761 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4762 r_refdef.viewcache.entityvisible[i] = 0;
4769 // no worldmodel or it can't check visibility
4770 for (i = 0;i < r_refdef.scene.numentities;i++)
4772 ent = r_refdef.scene.entities[i];
4773 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));
4778 /// only used if skyrendermasked, and normally returns false
4779 int R_DrawBrushModelsSky (void)
4782 entity_render_t *ent;
4785 for (i = 0;i < r_refdef.scene.numentities;i++)
4787 if (!r_refdef.viewcache.entityvisible[i])
4789 ent = r_refdef.scene.entities[i];
4790 if (!ent->model || !ent->model->DrawSky)
4792 ent->model->DrawSky(ent);
4798 static void R_DrawNoModel(entity_render_t *ent);
4799 static void R_DrawModels(void)
4802 entity_render_t *ent;
4804 for (i = 0;i < r_refdef.scene.numentities;i++)
4806 if (!r_refdef.viewcache.entityvisible[i])
4808 ent = r_refdef.scene.entities[i];
4809 r_refdef.stats.entities++;
4810 if (ent->model && ent->model->Draw != NULL)
4811 ent->model->Draw(ent);
4817 static void R_DrawModelsDepth(void)
4820 entity_render_t *ent;
4822 for (i = 0;i < r_refdef.scene.numentities;i++)
4824 if (!r_refdef.viewcache.entityvisible[i])
4826 ent = r_refdef.scene.entities[i];
4827 if (ent->model && ent->model->DrawDepth != NULL)
4828 ent->model->DrawDepth(ent);
4832 static void R_DrawModelsDebug(void)
4835 entity_render_t *ent;
4837 for (i = 0;i < r_refdef.scene.numentities;i++)
4839 if (!r_refdef.viewcache.entityvisible[i])
4841 ent = r_refdef.scene.entities[i];
4842 if (ent->model && ent->model->DrawDebug != NULL)
4843 ent->model->DrawDebug(ent);
4847 static void R_DrawModelsAddWaterPlanes(void)
4850 entity_render_t *ent;
4852 for (i = 0;i < r_refdef.scene.numentities;i++)
4854 if (!r_refdef.viewcache.entityvisible[i])
4856 ent = r_refdef.scene.entities[i];
4857 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4858 ent->model->DrawAddWaterPlanes(ent);
4862 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4864 if (r_hdr_irisadaptation.integer)
4868 vec3_t diffusenormal;
4873 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4874 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4875 brightness = max(0.0000001f, brightness);
4876 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4877 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4878 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4879 current = r_hdr_irisadaptation_value.value;
4881 current = min(current + adjust, goal);
4882 else if (current > goal)
4883 current = max(current - adjust, goal);
4884 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4885 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4887 else if (r_hdr_irisadaptation_value.value != 1.0f)
4888 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4891 static void R_View_SetFrustum(const int *scissor)
4894 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4895 vec3_t forward, left, up, origin, v;
4899 // flipped x coordinates (because x points left here)
4900 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4901 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4903 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4904 switch(vid.renderpath)
4906 case RENDERPATH_D3D9:
4907 case RENDERPATH_D3D10:
4908 case RENDERPATH_D3D11:
4909 case RENDERPATH_SOFT:
4910 // non-flipped y coordinates
4911 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4912 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4914 case RENDERPATH_GL11:
4915 case RENDERPATH_GL13:
4916 case RENDERPATH_GL20:
4917 case RENDERPATH_GLES2:
4918 // non-flipped y coordinates
4919 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4920 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4925 // we can't trust r_refdef.view.forward and friends in reflected scenes
4926 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4929 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4930 r_refdef.view.frustum[0].normal[1] = 0 - 0;
4931 r_refdef.view.frustum[0].normal[2] = -1 - 0;
4932 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4933 r_refdef.view.frustum[1].normal[1] = 0 + 0;
4934 r_refdef.view.frustum[1].normal[2] = -1 + 0;
4935 r_refdef.view.frustum[2].normal[0] = 0 - 0;
4936 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4937 r_refdef.view.frustum[2].normal[2] = -1 - 0;
4938 r_refdef.view.frustum[3].normal[0] = 0 + 0;
4939 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4940 r_refdef.view.frustum[3].normal[2] = -1 + 0;
4944 zNear = r_refdef.nearclip;
4945 nudge = 1.0 - 1.0 / (1<<23);
4946 r_refdef.view.frustum[4].normal[0] = 0 - 0;
4947 r_refdef.view.frustum[4].normal[1] = 0 - 0;
4948 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4949 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4950 r_refdef.view.frustum[5].normal[0] = 0 + 0;
4951 r_refdef.view.frustum[5].normal[1] = 0 + 0;
4952 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4953 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4959 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4960 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4961 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4962 r_refdef.view.frustum[0].dist = m[15] - m[12];
4964 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4965 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4966 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4967 r_refdef.view.frustum[1].dist = m[15] + m[12];
4969 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4970 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4971 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4972 r_refdef.view.frustum[2].dist = m[15] - m[13];
4974 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4975 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4976 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4977 r_refdef.view.frustum[3].dist = m[15] + m[13];
4979 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4980 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4981 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4982 r_refdef.view.frustum[4].dist = m[15] - m[14];
4984 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
4985 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
4986 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
4987 r_refdef.view.frustum[5].dist = m[15] + m[14];
4990 if (r_refdef.view.useperspective)
4992 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
4993 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]);
4994 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]);
4995 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]);
4996 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]);
4998 // then the normals from the corners relative to origin
4999 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5000 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5001 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5002 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5004 // in a NORMAL view, forward cross left == up
5005 // in a REFLECTED view, forward cross left == down
5006 // so our cross products above need to be adjusted for a left handed coordinate system
5007 CrossProduct(forward, left, v);
5008 if(DotProduct(v, up) < 0)
5010 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5011 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5012 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5013 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5016 // Leaving those out was a mistake, those were in the old code, and they
5017 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5018 // I couldn't reproduce it after adding those normalizations. --blub
5019 VectorNormalize(r_refdef.view.frustum[0].normal);
5020 VectorNormalize(r_refdef.view.frustum[1].normal);
5021 VectorNormalize(r_refdef.view.frustum[2].normal);
5022 VectorNormalize(r_refdef.view.frustum[3].normal);
5024 // make the corners absolute
5025 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5026 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5027 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5028 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5031 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5033 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5034 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5035 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5036 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5037 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5041 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5042 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5043 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5044 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5045 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5046 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5047 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5048 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5049 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5050 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5052 r_refdef.view.numfrustumplanes = 5;
5054 if (r_refdef.view.useclipplane)
5056 r_refdef.view.numfrustumplanes = 6;
5057 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5060 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5061 PlaneClassify(r_refdef.view.frustum + i);
5063 // LordHavoc: note to all quake engine coders, Quake had a special case
5064 // for 90 degrees which assumed a square view (wrong), so I removed it,
5065 // Quake2 has it disabled as well.
5067 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5068 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5069 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5070 //PlaneClassify(&frustum[0]);
5072 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5073 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5074 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5075 //PlaneClassify(&frustum[1]);
5077 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5078 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5079 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5080 //PlaneClassify(&frustum[2]);
5082 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5083 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5084 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5085 //PlaneClassify(&frustum[3]);
5088 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5089 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5090 //PlaneClassify(&frustum[4]);
5093 void R_View_UpdateWithScissor(const int *myscissor)
5095 R_Main_ResizeViewCache();
5096 R_View_SetFrustum(myscissor);
5097 R_View_WorldVisibility(r_refdef.view.useclipplane);
5098 R_View_UpdateEntityVisible();
5099 R_View_UpdateEntityLighting();
5102 void R_View_Update(void)
5104 R_Main_ResizeViewCache();
5105 R_View_SetFrustum(NULL);
5106 R_View_WorldVisibility(r_refdef.view.useclipplane);
5107 R_View_UpdateEntityVisible();
5108 R_View_UpdateEntityLighting();
5111 void R_SetupView(qboolean allowwaterclippingplane)
5113 const float *customclipplane = NULL;
5115 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5117 // LordHavoc: couldn't figure out how to make this approach the
5118 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5119 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5120 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5121 dist = r_refdef.view.clipplane.dist;
5122 plane[0] = r_refdef.view.clipplane.normal[0];
5123 plane[1] = r_refdef.view.clipplane.normal[1];
5124 plane[2] = r_refdef.view.clipplane.normal[2];
5126 customclipplane = plane;
5129 if (!r_refdef.view.useperspective)
5130 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);
5131 else if (vid.stencil && r_useinfinitefarclip.integer)
5132 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);
5134 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);
5135 R_SetViewport(&r_refdef.view.viewport);
5138 void R_EntityMatrix(const matrix4x4_t *matrix)
5140 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5142 gl_modelmatrixchanged = false;
5143 gl_modelmatrix = *matrix;
5144 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5145 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5146 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5147 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5149 switch(vid.renderpath)
5151 case RENDERPATH_D3D9:
5153 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5154 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5157 case RENDERPATH_D3D10:
5158 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5160 case RENDERPATH_D3D11:
5161 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5163 case RENDERPATH_GL13:
5164 case RENDERPATH_GL11:
5165 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5167 case RENDERPATH_SOFT:
5168 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5169 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5171 case RENDERPATH_GL20:
5172 case RENDERPATH_GLES2:
5173 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5174 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5180 void R_ResetViewRendering2D(void)
5182 r_viewport_t viewport;
5185 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5186 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);
5187 R_SetViewport(&viewport);
5188 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5189 GL_Color(1, 1, 1, 1);
5190 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5191 GL_BlendFunc(GL_ONE, GL_ZERO);
5192 GL_ScissorTest(false);
5193 GL_DepthMask(false);
5194 GL_DepthRange(0, 1);
5195 GL_DepthTest(false);
5196 GL_DepthFunc(GL_LEQUAL);
5197 R_EntityMatrix(&identitymatrix);
5198 R_Mesh_ResetTextureState();
5199 GL_PolygonOffset(0, 0);
5200 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5201 switch(vid.renderpath)
5203 case RENDERPATH_GL11:
5204 case RENDERPATH_GL13:
5205 case RENDERPATH_GL20:
5206 case RENDERPATH_GLES2:
5207 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5209 case RENDERPATH_D3D9:
5210 case RENDERPATH_D3D10:
5211 case RENDERPATH_D3D11:
5212 case RENDERPATH_SOFT:
5215 GL_CullFace(GL_NONE);
5218 void R_ResetViewRendering3D(void)
5223 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5224 GL_Color(1, 1, 1, 1);
5225 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5226 GL_BlendFunc(GL_ONE, GL_ZERO);
5227 GL_ScissorTest(true);
5229 GL_DepthRange(0, 1);
5231 GL_DepthFunc(GL_LEQUAL);
5232 R_EntityMatrix(&identitymatrix);
5233 R_Mesh_ResetTextureState();
5234 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5235 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5236 switch(vid.renderpath)
5238 case RENDERPATH_GL11:
5239 case RENDERPATH_GL13:
5240 case RENDERPATH_GL20:
5241 case RENDERPATH_GLES2:
5242 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5244 case RENDERPATH_D3D9:
5245 case RENDERPATH_D3D10:
5246 case RENDERPATH_D3D11:
5247 case RENDERPATH_SOFT:
5250 GL_CullFace(r_refdef.view.cullface_back);
5255 R_RenderView_UpdateViewVectors
5258 static void R_RenderView_UpdateViewVectors(void)
5260 // break apart the view matrix into vectors for various purposes
5261 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5262 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5263 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5264 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5265 // make an inverted copy of the view matrix for tracking sprites
5266 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5269 void R_RenderScene(void);
5270 void R_RenderWaterPlanes(void);
5272 static void R_Water_StartFrame(void)
5275 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5276 r_waterstate_waterplane_t *p;
5278 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5281 switch(vid.renderpath)
5283 case RENDERPATH_GL20:
5284 case RENDERPATH_D3D9:
5285 case RENDERPATH_D3D10:
5286 case RENDERPATH_D3D11:
5287 case RENDERPATH_SOFT:
5288 case RENDERPATH_GLES2:
5290 case RENDERPATH_GL13:
5291 case RENDERPATH_GL11:
5295 // set waterwidth and waterheight to the water resolution that will be
5296 // used (often less than the screen resolution for faster rendering)
5297 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5298 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5300 // calculate desired texture sizes
5301 // can't use water if the card does not support the texture size
5302 if (!r_water.integer || r_showsurfaces.integer)
5303 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5304 else if (vid.support.arb_texture_non_power_of_two)
5306 texturewidth = waterwidth;
5307 textureheight = waterheight;
5308 camerawidth = waterwidth;
5309 cameraheight = waterheight;
5313 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5314 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5315 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5316 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5319 // allocate textures as needed
5320 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5322 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5323 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5325 if (p->texture_refraction)
5326 R_FreeTexture(p->texture_refraction);
5327 p->texture_refraction = NULL;
5328 if (p->texture_reflection)
5329 R_FreeTexture(p->texture_reflection);
5330 p->texture_reflection = NULL;
5331 if (p->texture_camera)
5332 R_FreeTexture(p->texture_camera);
5333 p->texture_camera = NULL;
5335 memset(&r_waterstate, 0, sizeof(r_waterstate));
5336 r_waterstate.texturewidth = texturewidth;
5337 r_waterstate.textureheight = textureheight;
5338 r_waterstate.camerawidth = camerawidth;
5339 r_waterstate.cameraheight = cameraheight;
5342 if (r_waterstate.texturewidth)
5344 r_waterstate.enabled = true;
5346 // when doing a reduced render (HDR) we want to use a smaller area
5347 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5348 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5350 // set up variables that will be used in shader setup
5351 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5352 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5353 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5354 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5357 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5358 r_waterstate.numwaterplanes = 0;
5361 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5363 int triangleindex, planeindex;
5369 r_waterstate_waterplane_t *p;
5370 texture_t *t = R_GetCurrentTexture(surface->texture);
5372 // just use the first triangle with a valid normal for any decisions
5373 VectorClear(normal);
5374 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5376 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5377 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5378 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5379 TriangleNormal(vert[0], vert[1], vert[2], normal);
5380 if (VectorLength2(normal) >= 0.001)
5384 VectorCopy(normal, plane.normal);
5385 VectorNormalize(plane.normal);
5386 plane.dist = DotProduct(vert[0], plane.normal);
5387 PlaneClassify(&plane);
5388 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5390 // skip backfaces (except if nocullface is set)
5391 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5393 VectorNegate(plane.normal, plane.normal);
5395 PlaneClassify(&plane);
5399 // find a matching plane if there is one
5400 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5401 if(p->camera_entity == t->camera_entity)
5402 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5404 if (planeindex >= r_waterstate.maxwaterplanes)
5405 return; // nothing we can do, out of planes
5407 // if this triangle does not fit any known plane rendered this frame, add one
5408 if (planeindex >= r_waterstate.numwaterplanes)
5410 // store the new plane
5411 r_waterstate.numwaterplanes++;
5413 // clear materialflags and pvs
5414 p->materialflags = 0;
5415 p->pvsvalid = false;
5416 p->camera_entity = t->camera_entity;
5417 VectorCopy(surface->mins, p->mins);
5418 VectorCopy(surface->maxs, p->maxs);
5423 p->mins[0] = min(p->mins[0], surface->mins[0]);
5424 p->mins[1] = min(p->mins[1], surface->mins[1]);
5425 p->mins[2] = min(p->mins[2], surface->mins[2]);
5426 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5427 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5428 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5430 // merge this surface's materialflags into the waterplane
5431 p->materialflags |= t->currentmaterialflags;
5432 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5434 // merge this surface's PVS into the waterplane
5435 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5436 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5437 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5439 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5445 static void R_Water_ProcessPlanes(void)
5448 r_refdef_view_t originalview;
5449 r_refdef_view_t myview;
5451 r_waterstate_waterplane_t *p;
5454 originalview = r_refdef.view;
5456 // make sure enough textures are allocated
5457 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5459 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5461 if (!p->texture_refraction)
5462 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);
5463 if (!p->texture_refraction)
5466 else if (p->materialflags & MATERIALFLAG_CAMERA)
5468 if (!p->texture_camera)
5469 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);
5470 if (!p->texture_camera)
5474 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5476 if (!p->texture_reflection)
5477 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);
5478 if (!p->texture_reflection)
5484 r_refdef.view = originalview;
5485 r_refdef.view.showdebug = false;
5486 r_refdef.view.width = r_waterstate.waterwidth;
5487 r_refdef.view.height = r_waterstate.waterheight;
5488 r_refdef.view.useclipplane = true;
5489 myview = r_refdef.view;
5490 r_waterstate.renderingscene = true;
5491 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5493 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5495 r_refdef.view = myview;
5496 if(r_water_scissormode.integer)
5499 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5500 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5503 // render reflected scene and copy into texture
5504 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5505 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5506 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5507 r_refdef.view.clipplane = p->plane;
5509 // reverse the cullface settings for this render
5510 r_refdef.view.cullface_front = GL_FRONT;
5511 r_refdef.view.cullface_back = GL_BACK;
5512 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5514 r_refdef.view.usecustompvs = true;
5516 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5518 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5521 R_ResetViewRendering3D();
5522 R_ClearScreen(r_refdef.fogenabled);
5523 if(r_water_scissormode.integer & 2)
5524 R_View_UpdateWithScissor(myscissor);
5527 if(r_water_scissormode.integer & 1)
5528 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5531 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);
5534 // render the normal view scene and copy into texture
5535 // (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)
5536 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5538 r_refdef.view = myview;
5539 if(r_water_scissormode.integer)
5542 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5543 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5546 r_waterstate.renderingrefraction = true;
5548 r_refdef.view.clipplane = p->plane;
5549 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5550 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5552 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5554 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5555 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5556 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5557 R_RenderView_UpdateViewVectors();
5558 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5560 r_refdef.view.usecustompvs = true;
5561 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);
5565 PlaneClassify(&r_refdef.view.clipplane);
5567 R_ResetViewRendering3D();
5568 R_ClearScreen(r_refdef.fogenabled);
5569 if(r_water_scissormode.integer & 2)
5570 R_View_UpdateWithScissor(myscissor);
5573 if(r_water_scissormode.integer & 1)
5574 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5577 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);
5578 r_waterstate.renderingrefraction = false;
5580 else if (p->materialflags & MATERIALFLAG_CAMERA)
5582 r_refdef.view = myview;
5584 r_refdef.view.clipplane = p->plane;
5585 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5586 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5588 r_refdef.view.width = r_waterstate.camerawidth;
5589 r_refdef.view.height = r_waterstate.cameraheight;
5590 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5591 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5593 if(p->camera_entity)
5595 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5596 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5599 // note: all of the view is used for displaying... so
5600 // there is no use in scissoring
5602 // reverse the cullface settings for this render
5603 r_refdef.view.cullface_front = GL_FRONT;
5604 r_refdef.view.cullface_back = GL_BACK;
5605 // also reverse the view matrix
5606 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
5607 R_RenderView_UpdateViewVectors();
5608 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5610 r_refdef.view.usecustompvs = true;
5611 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);
5614 // camera needs no clipplane
5615 r_refdef.view.useclipplane = false;
5617 PlaneClassify(&r_refdef.view.clipplane);
5619 R_ResetViewRendering3D();
5620 R_ClearScreen(r_refdef.fogenabled);
5624 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);
5625 r_waterstate.renderingrefraction = false;
5629 r_waterstate.renderingscene = false;
5630 r_refdef.view = originalview;
5631 R_ResetViewRendering3D();
5632 R_ClearScreen(r_refdef.fogenabled);
5636 r_refdef.view = originalview;
5637 r_waterstate.renderingscene = false;
5638 Cvar_SetValueQuick(&r_water, 0);
5639 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5643 void R_Bloom_StartFrame(void)
5645 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5647 switch(vid.renderpath)
5649 case RENDERPATH_GL20:
5650 case RENDERPATH_D3D9:
5651 case RENDERPATH_D3D10:
5652 case RENDERPATH_D3D11:
5653 case RENDERPATH_SOFT:
5654 case RENDERPATH_GLES2:
5656 case RENDERPATH_GL13:
5657 case RENDERPATH_GL11:
5661 // set bloomwidth and bloomheight to the bloom resolution that will be
5662 // used (often less than the screen resolution for faster rendering)
5663 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5664 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5665 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5666 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5667 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5669 // calculate desired texture sizes
5670 if (vid.support.arb_texture_non_power_of_two)
5672 screentexturewidth = r_refdef.view.width;
5673 screentextureheight = r_refdef.view.height;
5674 bloomtexturewidth = r_bloomstate.bloomwidth;
5675 bloomtextureheight = r_bloomstate.bloomheight;
5679 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
5680 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
5681 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
5682 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
5685 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))
5687 Cvar_SetValueQuick(&r_hdr, 0);
5688 Cvar_SetValueQuick(&r_bloom, 0);
5689 Cvar_SetValueQuick(&r_motionblur, 0);
5690 Cvar_SetValueQuick(&r_damageblur, 0);
5693 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)))
5694 screentexturewidth = screentextureheight = 0;
5695 if (!r_hdr.integer && !r_bloom.integer)
5696 bloomtexturewidth = bloomtextureheight = 0;
5698 // allocate textures as needed
5699 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
5701 if (r_bloomstate.texture_screen)
5702 R_FreeTexture(r_bloomstate.texture_screen);
5703 r_bloomstate.texture_screen = NULL;
5704 r_bloomstate.screentexturewidth = screentexturewidth;
5705 r_bloomstate.screentextureheight = screentextureheight;
5706 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5707 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);
5709 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
5711 if (r_bloomstate.texture_bloom)
5712 R_FreeTexture(r_bloomstate.texture_bloom);
5713 r_bloomstate.texture_bloom = NULL;
5714 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5715 r_bloomstate.bloomtextureheight = bloomtextureheight;
5716 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5717 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);
5720 // when doing a reduced render (HDR) we want to use a smaller area
5721 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5722 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5723 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5724 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5725 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5727 // set up a texcoord array for the full resolution screen image
5728 // (we have to keep this around to copy back during final render)
5729 r_bloomstate.screentexcoord2f[0] = 0;
5730 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
5731 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
5732 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
5733 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
5734 r_bloomstate.screentexcoord2f[5] = 0;
5735 r_bloomstate.screentexcoord2f[6] = 0;
5736 r_bloomstate.screentexcoord2f[7] = 0;
5738 // set up a texcoord array for the reduced resolution bloom image
5739 // (which will be additive blended over the screen image)
5740 r_bloomstate.bloomtexcoord2f[0] = 0;
5741 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5742 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5743 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5744 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5745 r_bloomstate.bloomtexcoord2f[5] = 0;
5746 r_bloomstate.bloomtexcoord2f[6] = 0;
5747 r_bloomstate.bloomtexcoord2f[7] = 0;
5749 switch(vid.renderpath)
5751 case RENDERPATH_GL11:
5752 case RENDERPATH_GL13:
5753 case RENDERPATH_GL20:
5754 case RENDERPATH_SOFT:
5755 case RENDERPATH_GLES2:
5757 case RENDERPATH_D3D9:
5758 case RENDERPATH_D3D10:
5759 case RENDERPATH_D3D11:
5762 for (i = 0;i < 4;i++)
5764 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5765 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5766 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5767 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5773 if (r_hdr.integer || r_bloom.integer)
5775 r_bloomstate.enabled = true;
5776 r_bloomstate.hdr = r_hdr.integer != 0;
5779 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);
5782 void R_Bloom_CopyBloomTexture(float colorscale)
5784 r_refdef.stats.bloom++;
5786 // scale down screen texture to the bloom texture size
5788 R_SetViewport(&r_bloomstate.viewport);
5789 GL_BlendFunc(GL_ONE, GL_ZERO);
5790 GL_Color(colorscale, colorscale, colorscale, 1);
5791 // 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...
5792 switch(vid.renderpath)
5794 case RENDERPATH_GL11:
5795 case RENDERPATH_GL13:
5796 case RENDERPATH_GL20:
5797 case RENDERPATH_SOFT:
5798 case RENDERPATH_GLES2:
5799 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5801 case RENDERPATH_D3D9:
5802 case RENDERPATH_D3D10:
5803 case RENDERPATH_D3D11:
5804 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5807 // TODO: do boxfilter scale-down in shader?
5808 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5809 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5810 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5812 // we now have a bloom image in the framebuffer
5813 // copy it into the bloom image texture for later processing
5814 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);
5815 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5818 void R_Bloom_CopyHDRTexture(void)
5820 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);
5821 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5824 void R_Bloom_MakeTexture(void)
5827 float xoffset, yoffset, r, brighten;
5829 r_refdef.stats.bloom++;
5831 R_ResetViewRendering2D();
5833 // we have a bloom image in the framebuffer
5835 R_SetViewport(&r_bloomstate.viewport);
5837 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5840 r = bound(0, r_bloom_colorexponent.value / x, 1);
5841 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5843 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5844 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5845 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5846 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5848 // copy the vertically blurred bloom view to a texture
5849 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);
5850 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5853 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5854 brighten = r_bloom_brighten.value;
5856 brighten *= r_hdr_range.value;
5857 brighten = sqrt(brighten);
5859 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5860 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5862 for (dir = 0;dir < 2;dir++)
5864 // blend on at multiple vertical offsets to achieve a vertical blur
5865 // TODO: do offset blends using GLSL
5866 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5867 GL_BlendFunc(GL_ONE, GL_ZERO);
5868 for (x = -range;x <= range;x++)
5870 if (!dir){xoffset = 0;yoffset = x;}
5871 else {xoffset = x;yoffset = 0;}
5872 xoffset /= (float)r_bloomstate.bloomtexturewidth;
5873 yoffset /= (float)r_bloomstate.bloomtextureheight;
5874 // compute a texcoord array with the specified x and y offset
5875 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
5876 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5877 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5878 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5879 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5880 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
5881 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
5882 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
5883 // this r value looks like a 'dot' particle, fading sharply to
5884 // black at the edges
5885 // (probably not realistic but looks good enough)
5886 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
5887 //r = brighten/(range*2+1);
5888 r = brighten / (range * 2 + 1);
5890 r *= (1 - x*x/(float)(range*range));
5891 GL_Color(r, r, r, 1);
5892 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
5893 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5894 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5895 GL_BlendFunc(GL_ONE, GL_ONE);
5898 // copy the vertically blurred bloom view to a texture
5899 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);
5900 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5904 void R_HDR_RenderBloomTexture(void)
5906 int oldwidth, oldheight;
5907 float oldcolorscale;
5908 qboolean oldwaterstate;
5910 oldwaterstate = r_waterstate.enabled;
5911 oldcolorscale = r_refdef.view.colorscale;
5912 oldwidth = r_refdef.view.width;
5913 oldheight = r_refdef.view.height;
5914 r_refdef.view.width = r_bloomstate.bloomwidth;
5915 r_refdef.view.height = r_bloomstate.bloomheight;
5917 if(r_hdr.integer < 2)
5918 r_waterstate.enabled = false;
5920 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
5921 // TODO: add exposure compensation features
5922 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
5924 r_refdef.view.showdebug = false;
5925 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
5927 R_ResetViewRendering3D();
5929 R_ClearScreen(r_refdef.fogenabled);
5930 if (r_timereport_active)
5931 R_TimeReport("HDRclear");
5934 if (r_timereport_active)
5935 R_TimeReport("visibility");
5937 // only do secondary renders with HDR if r_hdr is 2 or higher
5938 r_waterstate.numwaterplanes = 0;
5939 if (r_waterstate.enabled)
5940 R_RenderWaterPlanes();
5942 r_refdef.view.showdebug = true;
5944 r_waterstate.numwaterplanes = 0;
5946 R_ResetViewRendering2D();
5948 R_Bloom_CopyHDRTexture();
5949 R_Bloom_MakeTexture();
5951 // restore the view settings
5952 r_waterstate.enabled = oldwaterstate;
5953 r_refdef.view.width = oldwidth;
5954 r_refdef.view.height = oldheight;
5955 r_refdef.view.colorscale = oldcolorscale;
5957 R_ResetViewRendering3D();
5959 R_ClearScreen(r_refdef.fogenabled);
5960 if (r_timereport_active)
5961 R_TimeReport("viewclear");
5964 static void R_BlendView(void)
5966 unsigned int permutation;
5967 float uservecs[4][4];
5969 switch (vid.renderpath)
5971 case RENDERPATH_GL20:
5972 case RENDERPATH_D3D9:
5973 case RENDERPATH_D3D10:
5974 case RENDERPATH_D3D11:
5975 case RENDERPATH_SOFT:
5976 case RENDERPATH_GLES2:
5978 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
5979 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
5980 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
5981 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
5982 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
5984 if (r_bloomstate.texture_screen)
5986 // make sure the buffer is available
5987 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
5989 R_ResetViewRendering2D();
5991 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
5993 // declare variables
5995 static float avgspeed;
5997 speed = VectorLength(cl.movement_velocity);
5999 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6000 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6002 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6003 speed = bound(0, speed, 1);
6004 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6006 // calculate values into a standard alpha
6007 cl.motionbluralpha = 1 - exp(-
6009 (r_motionblur.value * speed / 80)
6011 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6014 max(0.0001, cl.time - cl.oldtime) // fps independent
6017 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6018 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6020 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6022 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6023 GL_Color(1, 1, 1, cl.motionbluralpha);
6024 switch(vid.renderpath)
6026 case RENDERPATH_GL11:
6027 case RENDERPATH_GL13:
6028 case RENDERPATH_GL20:
6029 case RENDERPATH_SOFT:
6030 case RENDERPATH_GLES2:
6031 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6033 case RENDERPATH_D3D9:
6034 case RENDERPATH_D3D10:
6035 case RENDERPATH_D3D11:
6036 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6039 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6040 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6041 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6045 // copy view into the screen texture
6046 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);
6047 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6049 else if (!r_bloomstate.texture_bloom)
6051 // we may still have to do view tint...
6052 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6054 // apply a color tint to the whole view
6055 R_ResetViewRendering2D();
6056 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6057 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6058 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6059 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6060 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6062 break; // no screen processing, no bloom, skip it
6065 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6067 // render simple bloom effect
6068 // copy the screen and shrink it and darken it for the bloom process
6069 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6070 // make the bloom texture
6071 R_Bloom_MakeTexture();
6074 #if _MSC_VER >= 1400
6075 #define sscanf sscanf_s
6077 memset(uservecs, 0, sizeof(uservecs));
6078 if (r_glsl_postprocess_uservec1_enable.integer)
6079 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6080 if (r_glsl_postprocess_uservec2_enable.integer)
6081 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6082 if (r_glsl_postprocess_uservec3_enable.integer)
6083 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6084 if (r_glsl_postprocess_uservec4_enable.integer)
6085 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6087 R_ResetViewRendering2D();
6088 GL_Color(1, 1, 1, 1);
6089 GL_BlendFunc(GL_ONE, GL_ZERO);
6091 switch(vid.renderpath)
6093 case RENDERPATH_GL20:
6094 case RENDERPATH_GLES2:
6095 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6096 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6097 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6098 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6099 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6100 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]);
6101 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6102 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]);
6103 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]);
6104 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]);
6105 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]);
6106 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6107 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6108 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);
6110 case RENDERPATH_D3D9:
6112 // 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...
6113 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6114 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6115 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6116 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6117 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6118 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6119 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6120 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6121 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6122 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6123 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6124 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6125 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6126 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6129 case RENDERPATH_D3D10:
6130 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6132 case RENDERPATH_D3D11:
6133 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6135 case RENDERPATH_SOFT:
6136 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6137 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6138 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6139 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6140 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6141 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6142 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6143 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6144 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6145 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6146 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6147 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6148 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6149 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6154 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6155 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6157 case RENDERPATH_GL13:
6158 case RENDERPATH_GL11:
6159 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6161 // apply a color tint to the whole view
6162 R_ResetViewRendering2D();
6163 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6164 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6165 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6166 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6167 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6173 matrix4x4_t r_waterscrollmatrix;
6175 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6177 if (r_refdef.fog_density)
6179 r_refdef.fogcolor[0] = r_refdef.fog_red;
6180 r_refdef.fogcolor[1] = r_refdef.fog_green;
6181 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6183 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6184 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6185 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6186 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6190 VectorCopy(r_refdef.fogcolor, fogvec);
6191 // color.rgb *= ContrastBoost * SceneBrightness;
6192 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6193 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6194 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6195 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6200 void R_UpdateVariables(void)
6204 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6206 r_refdef.farclip = r_farclip_base.value;
6207 if (r_refdef.scene.worldmodel)
6208 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6209 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6211 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6212 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6213 r_refdef.polygonfactor = 0;
6214 r_refdef.polygonoffset = 0;
6215 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6216 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6218 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6219 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6220 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6221 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6222 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6223 if (FAKELIGHT_ENABLED)
6225 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6227 if (r_showsurfaces.integer)
6229 r_refdef.scene.rtworld = false;
6230 r_refdef.scene.rtworldshadows = false;
6231 r_refdef.scene.rtdlight = false;
6232 r_refdef.scene.rtdlightshadows = false;
6233 r_refdef.lightmapintensity = 0;
6236 if (gamemode == GAME_NEHAHRA)
6238 if (gl_fogenable.integer)
6240 r_refdef.oldgl_fogenable = true;
6241 r_refdef.fog_density = gl_fogdensity.value;
6242 r_refdef.fog_red = gl_fogred.value;
6243 r_refdef.fog_green = gl_foggreen.value;
6244 r_refdef.fog_blue = gl_fogblue.value;
6245 r_refdef.fog_alpha = 1;
6246 r_refdef.fog_start = 0;
6247 r_refdef.fog_end = gl_skyclip.value;
6248 r_refdef.fog_height = 1<<30;
6249 r_refdef.fog_fadedepth = 128;
6251 else if (r_refdef.oldgl_fogenable)
6253 r_refdef.oldgl_fogenable = false;
6254 r_refdef.fog_density = 0;
6255 r_refdef.fog_red = 0;
6256 r_refdef.fog_green = 0;
6257 r_refdef.fog_blue = 0;
6258 r_refdef.fog_alpha = 0;
6259 r_refdef.fog_start = 0;
6260 r_refdef.fog_end = 0;
6261 r_refdef.fog_height = 1<<30;
6262 r_refdef.fog_fadedepth = 128;
6266 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6267 r_refdef.fog_start = max(0, r_refdef.fog_start);
6268 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6270 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6272 if (r_refdef.fog_density && r_drawfog.integer)
6274 r_refdef.fogenabled = true;
6275 // this is the point where the fog reaches 0.9986 alpha, which we
6276 // consider a good enough cutoff point for the texture
6277 // (0.9986 * 256 == 255.6)
6278 if (r_fog_exp2.integer)
6279 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6281 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6282 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6283 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6284 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6285 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6286 R_BuildFogHeightTexture();
6287 // fog color was already set
6288 // update the fog texture
6289 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)
6290 R_BuildFogTexture();
6291 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6292 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6295 r_refdef.fogenabled = false;
6297 switch(vid.renderpath)
6299 case RENDERPATH_GL20:
6300 case RENDERPATH_D3D9:
6301 case RENDERPATH_D3D10:
6302 case RENDERPATH_D3D11:
6303 case RENDERPATH_SOFT:
6304 case RENDERPATH_GLES2:
6305 if(v_glslgamma.integer && !vid_gammatables_trivial)
6307 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6309 // build GLSL gamma texture
6310 #define RAMPWIDTH 256
6311 unsigned short ramp[RAMPWIDTH * 3];
6312 unsigned char rampbgr[RAMPWIDTH][4];
6315 r_texture_gammaramps_serial = vid_gammatables_serial;
6317 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6318 for(i = 0; i < RAMPWIDTH; ++i)
6320 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6321 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6322 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6325 if (r_texture_gammaramps)
6327 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6331 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6337 // remove GLSL gamma texture
6340 case RENDERPATH_GL13:
6341 case RENDERPATH_GL11:
6346 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6347 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6353 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6354 if( scenetype != r_currentscenetype ) {
6355 // store the old scenetype
6356 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6357 r_currentscenetype = scenetype;
6358 // move in the new scene
6359 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6368 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6370 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6371 if( scenetype == r_currentscenetype ) {
6372 return &r_refdef.scene;
6374 return &r_scenes_store[ scenetype ];
6383 int dpsoftrast_test;
6384 void R_RenderView(void)
6386 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6388 dpsoftrast_test = r_test.integer;
6390 if (r_timereport_active)
6391 R_TimeReport("start");
6392 r_textureframe++; // used only by R_GetCurrentTexture
6393 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6395 if(R_CompileShader_CheckStaticParms())
6398 if (!r_drawentities.integer)
6399 r_refdef.scene.numentities = 0;
6401 R_AnimCache_ClearCache();
6402 R_FrameData_NewFrame();
6404 /* adjust for stereo display */
6405 if(R_Stereo_Active())
6407 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);
6408 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6411 if (r_refdef.view.isoverlay)
6413 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6414 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6415 R_TimeReport("depthclear");
6417 r_refdef.view.showdebug = false;
6419 r_waterstate.enabled = false;
6420 r_waterstate.numwaterplanes = 0;
6424 r_refdef.view.matrix = originalmatrix;
6430 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6432 r_refdef.view.matrix = originalmatrix;
6433 return; //Host_Error ("R_RenderView: NULL worldmodel");
6436 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6438 R_RenderView_UpdateViewVectors();
6440 R_Shadow_UpdateWorldLightSelection();
6442 R_Bloom_StartFrame();
6443 R_Water_StartFrame();
6446 if (r_timereport_active)
6447 R_TimeReport("viewsetup");
6449 R_ResetViewRendering3D();
6451 if (r_refdef.view.clear || r_refdef.fogenabled)
6453 R_ClearScreen(r_refdef.fogenabled);
6454 if (r_timereport_active)
6455 R_TimeReport("viewclear");
6457 r_refdef.view.clear = true;
6459 // this produces a bloom texture to be used in R_BlendView() later
6460 if (r_hdr.integer && r_bloomstate.bloomwidth)
6462 R_HDR_RenderBloomTexture();
6463 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6464 r_textureframe++; // used only by R_GetCurrentTexture
6467 r_refdef.view.showdebug = true;
6470 if (r_timereport_active)
6471 R_TimeReport("visibility");
6473 r_waterstate.numwaterplanes = 0;
6474 if (r_waterstate.enabled)
6475 R_RenderWaterPlanes();
6478 r_waterstate.numwaterplanes = 0;
6481 if (r_timereport_active)
6482 R_TimeReport("blendview");
6484 GL_Scissor(0, 0, vid.width, vid.height);
6485 GL_ScissorTest(false);
6487 r_refdef.view.matrix = originalmatrix;
6492 void R_RenderWaterPlanes(void)
6494 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6496 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6497 if (r_timereport_active)
6498 R_TimeReport("waterworld");
6501 // don't let sound skip if going slow
6502 if (r_refdef.scene.extraupdate)
6505 R_DrawModelsAddWaterPlanes();
6506 if (r_timereport_active)
6507 R_TimeReport("watermodels");
6509 if (r_waterstate.numwaterplanes)
6511 R_Water_ProcessPlanes();
6512 if (r_timereport_active)
6513 R_TimeReport("waterscenes");
6517 extern void R_DrawLightningBeams (void);
6518 extern void VM_CL_AddPolygonsToMeshQueue (void);
6519 extern void R_DrawPortals (void);
6520 extern cvar_t cl_locs_show;
6521 static void R_DrawLocs(void);
6522 static void R_DrawEntityBBoxes(void);
6523 static void R_DrawModelDecals(void);
6524 extern void R_DrawModelShadows(void);
6525 extern void R_DrawModelShadowMaps(void);
6526 extern cvar_t cl_decals_newsystem;
6527 extern qboolean r_shadow_usingdeferredprepass;
6528 void R_RenderScene(void)
6530 qboolean shadowmapping = false;
6532 if (r_timereport_active)
6533 R_TimeReport("beginscene");
6535 r_refdef.stats.renders++;
6539 // don't let sound skip if going slow
6540 if (r_refdef.scene.extraupdate)
6543 R_MeshQueue_BeginScene();
6547 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);
6549 if (r_timereport_active)
6550 R_TimeReport("skystartframe");
6552 if (cl.csqc_vidvars.drawworld)
6554 // don't let sound skip if going slow
6555 if (r_refdef.scene.extraupdate)
6558 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6560 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6561 if (r_timereport_active)
6562 R_TimeReport("worldsky");
6565 if (R_DrawBrushModelsSky() && r_timereport_active)
6566 R_TimeReport("bmodelsky");
6568 if (skyrendermasked && skyrenderlater)
6570 // we have to force off the water clipping plane while rendering sky
6574 if (r_timereport_active)
6575 R_TimeReport("sky");
6579 R_AnimCache_CacheVisibleEntities();
6580 if (r_timereport_active)
6581 R_TimeReport("animation");
6583 R_Shadow_PrepareLights();
6584 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6585 R_Shadow_PrepareModelShadows();
6586 if (r_timereport_active)
6587 R_TimeReport("preparelights");
6589 if (R_Shadow_ShadowMappingEnabled())
6590 shadowmapping = true;
6592 if (r_shadow_usingdeferredprepass)
6593 R_Shadow_DrawPrepass();
6595 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6597 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6598 if (r_timereport_active)
6599 R_TimeReport("worlddepth");
6601 if (r_depthfirst.integer >= 2)
6603 R_DrawModelsDepth();
6604 if (r_timereport_active)
6605 R_TimeReport("modeldepth");
6608 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6610 R_DrawModelShadowMaps();
6611 R_ResetViewRendering3D();
6612 // don't let sound skip if going slow
6613 if (r_refdef.scene.extraupdate)
6617 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6619 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6620 if (r_timereport_active)
6621 R_TimeReport("world");
6624 // don't let sound skip if going slow
6625 if (r_refdef.scene.extraupdate)
6629 if (r_timereport_active)
6630 R_TimeReport("models");
6632 // don't let sound skip if going slow
6633 if (r_refdef.scene.extraupdate)
6636 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6638 R_DrawModelShadows();
6639 R_ResetViewRendering3D();
6640 // don't let sound skip if going slow
6641 if (r_refdef.scene.extraupdate)
6645 if (!r_shadow_usingdeferredprepass)
6647 R_Shadow_DrawLights();
6648 if (r_timereport_active)
6649 R_TimeReport("rtlights");
6652 // don't let sound skip if going slow
6653 if (r_refdef.scene.extraupdate)
6656 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6658 R_DrawModelShadows();
6659 R_ResetViewRendering3D();
6660 // don't let sound skip if going slow
6661 if (r_refdef.scene.extraupdate)
6665 if (cl.csqc_vidvars.drawworld)
6667 if (cl_decals_newsystem.integer)
6669 R_DrawModelDecals();
6670 if (r_timereport_active)
6671 R_TimeReport("modeldecals");
6676 if (r_timereport_active)
6677 R_TimeReport("decals");
6681 if (r_timereport_active)
6682 R_TimeReport("particles");
6685 if (r_timereport_active)
6686 R_TimeReport("explosions");
6688 R_DrawLightningBeams();
6689 if (r_timereport_active)
6690 R_TimeReport("lightning");
6693 VM_CL_AddPolygonsToMeshQueue();
6695 if (r_refdef.view.showdebug)
6697 if (cl_locs_show.integer)
6700 if (r_timereport_active)
6701 R_TimeReport("showlocs");
6704 if (r_drawportals.integer)
6707 if (r_timereport_active)
6708 R_TimeReport("portals");
6711 if (r_showbboxes.value > 0)
6713 R_DrawEntityBBoxes();
6714 if (r_timereport_active)
6715 R_TimeReport("bboxes");
6719 R_MeshQueue_RenderTransparent();
6720 if (r_timereport_active)
6721 R_TimeReport("drawtrans");
6723 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))
6725 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6726 if (r_timereport_active)
6727 R_TimeReport("worlddebug");
6728 R_DrawModelsDebug();
6729 if (r_timereport_active)
6730 R_TimeReport("modeldebug");
6733 if (cl.csqc_vidvars.drawworld)
6735 R_Shadow_DrawCoronas();
6736 if (r_timereport_active)
6737 R_TimeReport("coronas");
6742 GL_DepthTest(false);
6743 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6744 GL_Color(1, 1, 1, 1);
6745 qglBegin(GL_POLYGON);
6746 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6747 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6748 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6749 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6751 qglBegin(GL_POLYGON);
6752 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]);
6753 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]);
6754 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]);
6755 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]);
6757 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6761 // don't let sound skip if going slow
6762 if (r_refdef.scene.extraupdate)
6765 R_ResetViewRendering2D();
6768 static const unsigned short bboxelements[36] =
6778 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6781 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6783 RSurf_ActiveWorldEntity();
6785 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6786 GL_DepthMask(false);
6787 GL_DepthRange(0, 1);
6788 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6789 // R_Mesh_ResetTextureState();
6791 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6792 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6793 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6794 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6795 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6796 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6797 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6798 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6799 R_FillColors(color4f, 8, cr, cg, cb, ca);
6800 if (r_refdef.fogenabled)
6802 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6804 f1 = RSurf_FogVertex(v);
6806 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6807 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6808 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6811 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6812 R_Mesh_ResetTextureState();
6813 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6814 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6817 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6821 prvm_edict_t *edict;
6822 prvm_prog_t *prog_save = prog;
6824 // this function draws bounding boxes of server entities
6828 GL_CullFace(GL_NONE);
6829 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6833 for (i = 0;i < numsurfaces;i++)
6835 edict = PRVM_EDICT_NUM(surfacelist[i]);
6836 switch ((int)edict->fields.server->solid)
6838 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
6839 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
6840 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
6841 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6842 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
6843 default: Vector4Set(color, 0, 0, 0, 0.50);break;
6845 color[3] *= r_showbboxes.value;
6846 color[3] = bound(0, color[3], 1);
6847 GL_DepthTest(!r_showdisabledepthtest.integer);
6848 GL_CullFace(r_refdef.view.cullface_front);
6849 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6855 static void R_DrawEntityBBoxes(void)
6858 prvm_edict_t *edict;
6860 prvm_prog_t *prog_save = prog;
6862 // this function draws bounding boxes of server entities
6868 for (i = 0;i < prog->num_edicts;i++)
6870 edict = PRVM_EDICT_NUM(i);
6871 if (edict->priv.server->free)
6873 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6874 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
6876 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
6878 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
6879 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
6885 static const int nomodelelement3i[24] =
6897 static const unsigned short nomodelelement3s[24] =
6909 static const float nomodelvertex3f[6*3] =
6919 static const float nomodelcolor4f[6*4] =
6921 0.0f, 0.0f, 0.5f, 1.0f,
6922 0.0f, 0.0f, 0.5f, 1.0f,
6923 0.0f, 0.5f, 0.0f, 1.0f,
6924 0.0f, 0.5f, 0.0f, 1.0f,
6925 0.5f, 0.0f, 0.0f, 1.0f,
6926 0.5f, 0.0f, 0.0f, 1.0f
6929 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6935 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);
6937 // this is only called once per entity so numsurfaces is always 1, and
6938 // surfacelist is always {0}, so this code does not handle batches
6940 if (rsurface.ent_flags & RENDER_ADDITIVE)
6942 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
6943 GL_DepthMask(false);
6945 else if (rsurface.colormod[3] < 1)
6947 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6948 GL_DepthMask(false);
6952 GL_BlendFunc(GL_ONE, GL_ZERO);
6955 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
6956 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
6957 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
6958 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
6959 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
6960 for (i = 0, c = color4f;i < 6;i++, c += 4)
6962 c[0] *= rsurface.colormod[0];
6963 c[1] *= rsurface.colormod[1];
6964 c[2] *= rsurface.colormod[2];
6965 c[3] *= rsurface.colormod[3];
6967 if (r_refdef.fogenabled)
6969 for (i = 0, c = color4f;i < 6;i++, c += 4)
6971 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
6973 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
6974 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
6975 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
6978 // R_Mesh_ResetTextureState();
6979 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6980 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
6981 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
6984 void R_DrawNoModel(entity_render_t *ent)
6987 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6988 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
6989 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
6991 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
6994 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
6996 vec3_t right1, right2, diff, normal;
6998 VectorSubtract (org2, org1, normal);
7000 // calculate 'right' vector for start
7001 VectorSubtract (r_refdef.view.origin, org1, diff);
7002 CrossProduct (normal, diff, right1);
7003 VectorNormalize (right1);
7005 // calculate 'right' vector for end
7006 VectorSubtract (r_refdef.view.origin, org2, diff);
7007 CrossProduct (normal, diff, right2);
7008 VectorNormalize (right2);
7010 vert[ 0] = org1[0] + width * right1[0];
7011 vert[ 1] = org1[1] + width * right1[1];
7012 vert[ 2] = org1[2] + width * right1[2];
7013 vert[ 3] = org1[0] - width * right1[0];
7014 vert[ 4] = org1[1] - width * right1[1];
7015 vert[ 5] = org1[2] - width * right1[2];
7016 vert[ 6] = org2[0] - width * right2[0];
7017 vert[ 7] = org2[1] - width * right2[1];
7018 vert[ 8] = org2[2] - width * right2[2];
7019 vert[ 9] = org2[0] + width * right2[0];
7020 vert[10] = org2[1] + width * right2[1];
7021 vert[11] = org2[2] + width * right2[2];
7024 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)
7026 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7027 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7028 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7029 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7030 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7031 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7032 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7033 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7034 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7035 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7036 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7037 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7040 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7045 VectorSet(v, x, y, z);
7046 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7047 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7049 if (i == mesh->numvertices)
7051 if (mesh->numvertices < mesh->maxvertices)
7053 VectorCopy(v, vertex3f);
7054 mesh->numvertices++;
7056 return mesh->numvertices;
7062 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7066 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7067 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7068 e = mesh->element3i + mesh->numtriangles * 3;
7069 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7071 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7072 if (mesh->numtriangles < mesh->maxtriangles)
7077 mesh->numtriangles++;
7079 element[1] = element[2];
7083 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7087 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7088 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7089 e = mesh->element3i + mesh->numtriangles * 3;
7090 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7092 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7093 if (mesh->numtriangles < mesh->maxtriangles)
7098 mesh->numtriangles++;
7100 element[1] = element[2];
7104 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7105 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7107 int planenum, planenum2;
7110 mplane_t *plane, *plane2;
7112 double temppoints[2][256*3];
7113 // figure out how large a bounding box we need to properly compute this brush
7115 for (w = 0;w < numplanes;w++)
7116 maxdist = max(maxdist, fabs(planes[w].dist));
7117 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7118 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7119 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7123 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7124 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7126 if (planenum2 == planenum)
7128 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);
7131 if (tempnumpoints < 3)
7133 // generate elements forming a triangle fan for this polygon
7134 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7138 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)
7140 texturelayer_t *layer;
7141 layer = t->currentlayers + t->currentnumlayers++;
7143 layer->depthmask = depthmask;
7144 layer->blendfunc1 = blendfunc1;
7145 layer->blendfunc2 = blendfunc2;
7146 layer->texture = texture;
7147 layer->texmatrix = *matrix;
7148 layer->color[0] = r;
7149 layer->color[1] = g;
7150 layer->color[2] = b;
7151 layer->color[3] = a;
7154 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7156 if(parms[0] == 0 && parms[1] == 0)
7158 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7159 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7164 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7167 index = parms[2] + r_refdef.scene.time * parms[3];
7168 index -= floor(index);
7169 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7172 case Q3WAVEFUNC_NONE:
7173 case Q3WAVEFUNC_NOISE:
7174 case Q3WAVEFUNC_COUNT:
7177 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7178 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7179 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7180 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7181 case Q3WAVEFUNC_TRIANGLE:
7183 f = index - floor(index);
7194 f = parms[0] + parms[1] * f;
7195 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7196 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7200 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7205 matrix4x4_t matrix, temp;
7206 switch(tcmod->tcmod)
7210 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7211 matrix = r_waterscrollmatrix;
7213 matrix = identitymatrix;
7215 case Q3TCMOD_ENTITYTRANSLATE:
7216 // this is used in Q3 to allow the gamecode to control texcoord
7217 // scrolling on the entity, which is not supported in darkplaces yet.
7218 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7220 case Q3TCMOD_ROTATE:
7221 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7222 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7223 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7226 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7228 case Q3TCMOD_SCROLL:
7229 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7231 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7232 w = (int) tcmod->parms[0];
7233 h = (int) tcmod->parms[1];
7234 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7236 idx = (int) floor(f * w * h);
7237 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7239 case Q3TCMOD_STRETCH:
7240 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7241 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7243 case Q3TCMOD_TRANSFORM:
7244 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7245 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7246 VectorSet(tcmat + 6, 0 , 0 , 1);
7247 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7248 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7250 case Q3TCMOD_TURBULENT:
7251 // this is handled in the RSurf_PrepareVertices function
7252 matrix = identitymatrix;
7256 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7259 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7261 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7262 char name[MAX_QPATH];
7263 skinframe_t *skinframe;
7264 unsigned char pixels[296*194];
7265 strlcpy(cache->name, skinname, sizeof(cache->name));
7266 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7267 if (developer_loading.integer)
7268 Con_Printf("loading %s\n", name);
7269 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7270 if (!skinframe || !skinframe->base)
7273 fs_offset_t filesize;
7275 f = FS_LoadFile(name, tempmempool, true, &filesize);
7278 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7279 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7283 cache->skinframe = skinframe;
7286 texture_t *R_GetCurrentTexture(texture_t *t)
7289 const entity_render_t *ent = rsurface.entity;
7290 dp_model_t *model = ent->model;
7291 q3shaderinfo_layer_tcmod_t *tcmod;
7293 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7294 return t->currentframe;
7295 t->update_lastrenderframe = r_textureframe;
7296 t->update_lastrenderentity = (void *)ent;
7298 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7299 t->camera_entity = ent->entitynumber;
7301 t->camera_entity = 0;
7303 // switch to an alternate material if this is a q1bsp animated material
7305 texture_t *texture = t;
7306 int s = rsurface.ent_skinnum;
7307 if ((unsigned int)s >= (unsigned int)model->numskins)
7309 if (model->skinscenes)
7311 if (model->skinscenes[s].framecount > 1)
7312 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7314 s = model->skinscenes[s].firstframe;
7317 t = t + s * model->num_surfaces;
7320 // use an alternate animation if the entity's frame is not 0,
7321 // and only if the texture has an alternate animation
7322 if (rsurface.ent_alttextures && t->anim_total[1])
7323 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7325 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7327 texture->currentframe = t;
7330 // update currentskinframe to be a qw skin or animation frame
7331 if (rsurface.ent_qwskin >= 0)
7333 i = rsurface.ent_qwskin;
7334 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7336 r_qwskincache_size = cl.maxclients;
7338 Mem_Free(r_qwskincache);
7339 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7341 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7342 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7343 t->currentskinframe = r_qwskincache[i].skinframe;
7344 if (t->currentskinframe == NULL)
7345 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7347 else if (t->numskinframes >= 2)
7348 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7349 if (t->backgroundnumskinframes >= 2)
7350 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7352 t->currentmaterialflags = t->basematerialflags;
7353 t->currentalpha = rsurface.colormod[3];
7354 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7355 t->currentalpha *= r_wateralpha.value;
7356 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7357 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7358 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7359 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7360 if (!(rsurface.ent_flags & RENDER_LIGHT))
7361 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7362 else if (FAKELIGHT_ENABLED)
7364 // no modellight if using fakelight for the map
7366 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7368 // pick a model lighting mode
7369 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7370 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7372 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7374 if (rsurface.ent_flags & RENDER_ADDITIVE)
7375 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7376 else if (t->currentalpha < 1)
7377 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7378 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7379 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7380 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7381 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7382 if (t->backgroundnumskinframes)
7383 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7384 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7386 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7387 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7390 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7391 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7392 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7394 // there is no tcmod
7395 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7397 t->currenttexmatrix = r_waterscrollmatrix;
7398 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7400 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7402 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7403 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7406 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7407 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7408 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7409 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7411 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7412 if (t->currentskinframe->qpixels)
7413 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7414 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7415 if (!t->basetexture)
7416 t->basetexture = r_texture_notexture;
7417 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7418 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7419 t->nmaptexture = t->currentskinframe->nmap;
7420 if (!t->nmaptexture)
7421 t->nmaptexture = r_texture_blanknormalmap;
7422 t->glosstexture = r_texture_black;
7423 t->glowtexture = t->currentskinframe->glow;
7424 t->fogtexture = t->currentskinframe->fog;
7425 t->reflectmasktexture = t->currentskinframe->reflect;
7426 if (t->backgroundnumskinframes)
7428 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7429 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7430 t->backgroundglosstexture = r_texture_black;
7431 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7432 if (!t->backgroundnmaptexture)
7433 t->backgroundnmaptexture = r_texture_blanknormalmap;
7437 t->backgroundbasetexture = r_texture_white;
7438 t->backgroundnmaptexture = r_texture_blanknormalmap;
7439 t->backgroundglosstexture = r_texture_black;
7440 t->backgroundglowtexture = NULL;
7442 t->specularpower = r_shadow_glossexponent.value;
7443 // TODO: store reference values for these in the texture?
7444 t->specularscale = 0;
7445 if (r_shadow_gloss.integer > 0)
7447 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7449 if (r_shadow_glossintensity.value > 0)
7451 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7452 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7453 t->specularscale = r_shadow_glossintensity.value;
7456 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7458 t->glosstexture = r_texture_white;
7459 t->backgroundglosstexture = r_texture_white;
7460 t->specularscale = r_shadow_gloss2intensity.value;
7461 t->specularpower = r_shadow_gloss2exponent.value;
7464 t->specularscale *= t->specularscalemod;
7465 t->specularpower *= t->specularpowermod;
7467 // lightmaps mode looks bad with dlights using actual texturing, so turn
7468 // off the colormap and glossmap, but leave the normalmap on as it still
7469 // accurately represents the shading involved
7470 if (gl_lightmaps.integer)
7472 t->basetexture = r_texture_grey128;
7473 t->pantstexture = r_texture_black;
7474 t->shirttexture = r_texture_black;
7475 t->nmaptexture = r_texture_blanknormalmap;
7476 t->glosstexture = r_texture_black;
7477 t->glowtexture = NULL;
7478 t->fogtexture = NULL;
7479 t->reflectmasktexture = NULL;
7480 t->backgroundbasetexture = NULL;
7481 t->backgroundnmaptexture = r_texture_blanknormalmap;
7482 t->backgroundglosstexture = r_texture_black;
7483 t->backgroundglowtexture = NULL;
7484 t->specularscale = 0;
7485 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7488 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7489 VectorClear(t->dlightcolor);
7490 t->currentnumlayers = 0;
7491 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7493 int blendfunc1, blendfunc2;
7495 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7497 blendfunc1 = GL_SRC_ALPHA;
7498 blendfunc2 = GL_ONE;
7500 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7502 blendfunc1 = GL_SRC_ALPHA;
7503 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7505 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7507 blendfunc1 = t->customblendfunc[0];
7508 blendfunc2 = t->customblendfunc[1];
7512 blendfunc1 = GL_ONE;
7513 blendfunc2 = GL_ZERO;
7515 // don't colormod evilblend textures
7516 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7517 VectorSet(t->lightmapcolor, 1, 1, 1);
7518 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7519 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7521 // fullbright is not affected by r_refdef.lightmapintensity
7522 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]);
7523 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7524 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]);
7525 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7526 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]);
7530 vec3_t ambientcolor;
7532 // set the color tint used for lights affecting this surface
7533 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7535 // q3bsp has no lightmap updates, so the lightstylevalue that
7536 // would normally be baked into the lightmap must be
7537 // applied to the color
7538 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7539 if (model->type == mod_brushq3)
7540 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7541 colorscale *= r_refdef.lightmapintensity;
7542 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7543 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7544 // basic lit geometry
7545 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]);
7546 // add pants/shirt if needed
7547 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7548 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]);
7549 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7550 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]);
7551 // now add ambient passes if needed
7552 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7554 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]);
7555 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7556 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]);
7557 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7558 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]);
7561 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7562 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]);
7563 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7565 // if this is opaque use alpha blend which will darken the earlier
7568 // if this is an alpha blended material, all the earlier passes
7569 // were darkened by fog already, so we only need to add the fog
7570 // color ontop through the fog mask texture
7572 // if this is an additive blended material, all the earlier passes
7573 // were darkened by fog already, and we should not add fog color
7574 // (because the background was not darkened, there is no fog color
7575 // that was lost behind it).
7576 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]);
7580 return t->currentframe;
7583 rsurfacestate_t rsurface;
7585 void RSurf_ActiveWorldEntity(void)
7587 dp_model_t *model = r_refdef.scene.worldmodel;
7588 //if (rsurface.entity == r_refdef.scene.worldentity)
7590 rsurface.entity = r_refdef.scene.worldentity;
7591 rsurface.skeleton = NULL;
7592 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7593 rsurface.ent_skinnum = 0;
7594 rsurface.ent_qwskin = -1;
7595 rsurface.ent_shadertime = 0;
7596 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7597 rsurface.matrix = identitymatrix;
7598 rsurface.inversematrix = identitymatrix;
7599 rsurface.matrixscale = 1;
7600 rsurface.inversematrixscale = 1;
7601 R_EntityMatrix(&identitymatrix);
7602 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7603 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7604 rsurface.fograngerecip = r_refdef.fograngerecip;
7605 rsurface.fogheightfade = r_refdef.fogheightfade;
7606 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7607 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7608 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7609 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7610 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7611 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7612 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7613 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7614 rsurface.colormod[3] = 1;
7615 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);
7616 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7617 rsurface.frameblend[0].lerp = 1;
7618 rsurface.ent_alttextures = false;
7619 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7620 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7621 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7622 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7623 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7624 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7625 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7626 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7627 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7628 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7629 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7630 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7631 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7632 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7633 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7634 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7635 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7636 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7637 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7638 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7639 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7640 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7641 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7642 rsurface.modelelement3i = model->surfmesh.data_element3i;
7643 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7644 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7645 rsurface.modelelement3s = model->surfmesh.data_element3s;
7646 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7647 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7648 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7649 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7650 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7651 rsurface.modelsurfaces = model->data_surfaces;
7652 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7653 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7654 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7655 rsurface.modelgeneratedvertex = false;
7656 rsurface.batchgeneratedvertex = false;
7657 rsurface.batchfirstvertex = 0;
7658 rsurface.batchnumvertices = 0;
7659 rsurface.batchfirsttriangle = 0;
7660 rsurface.batchnumtriangles = 0;
7661 rsurface.batchvertex3f = NULL;
7662 rsurface.batchvertex3f_vertexbuffer = NULL;
7663 rsurface.batchvertex3f_bufferoffset = 0;
7664 rsurface.batchsvector3f = NULL;
7665 rsurface.batchsvector3f_vertexbuffer = NULL;
7666 rsurface.batchsvector3f_bufferoffset = 0;
7667 rsurface.batchtvector3f = NULL;
7668 rsurface.batchtvector3f_vertexbuffer = NULL;
7669 rsurface.batchtvector3f_bufferoffset = 0;
7670 rsurface.batchnormal3f = NULL;
7671 rsurface.batchnormal3f_vertexbuffer = NULL;
7672 rsurface.batchnormal3f_bufferoffset = 0;
7673 rsurface.batchlightmapcolor4f = NULL;
7674 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7675 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7676 rsurface.batchtexcoordtexture2f = NULL;
7677 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7678 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7679 rsurface.batchtexcoordlightmap2f = NULL;
7680 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7681 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7682 rsurface.batchvertexmesh = NULL;
7683 rsurface.batchvertexmeshbuffer = NULL;
7684 rsurface.batchvertex3fbuffer = NULL;
7685 rsurface.batchelement3i = NULL;
7686 rsurface.batchelement3i_indexbuffer = NULL;
7687 rsurface.batchelement3i_bufferoffset = 0;
7688 rsurface.batchelement3s = NULL;
7689 rsurface.batchelement3s_indexbuffer = NULL;
7690 rsurface.batchelement3s_bufferoffset = 0;
7691 rsurface.passcolor4f = NULL;
7692 rsurface.passcolor4f_vertexbuffer = NULL;
7693 rsurface.passcolor4f_bufferoffset = 0;
7696 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7698 dp_model_t *model = ent->model;
7699 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7701 rsurface.entity = (entity_render_t *)ent;
7702 rsurface.skeleton = ent->skeleton;
7703 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7704 rsurface.ent_skinnum = ent->skinnum;
7705 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;
7706 rsurface.ent_shadertime = ent->shadertime;
7707 rsurface.ent_flags = ent->flags;
7708 rsurface.matrix = ent->matrix;
7709 rsurface.inversematrix = ent->inversematrix;
7710 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7711 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7712 R_EntityMatrix(&rsurface.matrix);
7713 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7714 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7715 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7716 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7717 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7718 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7719 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7720 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7721 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7722 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7723 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7724 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7725 rsurface.colormod[3] = ent->alpha;
7726 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7727 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7728 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7729 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7730 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7731 if (ent->model->brush.submodel && !prepass)
7733 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7734 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7736 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7738 if (ent->animcache_vertex3f)
7740 rsurface.modelvertex3f = ent->animcache_vertex3f;
7741 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7742 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7743 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7744 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7745 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7746 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7748 else if (wanttangents)
7750 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7751 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7752 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7753 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7754 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7755 rsurface.modelvertexmesh = NULL;
7756 rsurface.modelvertexmeshbuffer = NULL;
7757 rsurface.modelvertex3fbuffer = NULL;
7759 else if (wantnormals)
7761 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7762 rsurface.modelsvector3f = NULL;
7763 rsurface.modeltvector3f = NULL;
7764 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7765 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7766 rsurface.modelvertexmesh = NULL;
7767 rsurface.modelvertexmeshbuffer = NULL;
7768 rsurface.modelvertex3fbuffer = NULL;
7772 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7773 rsurface.modelsvector3f = NULL;
7774 rsurface.modeltvector3f = NULL;
7775 rsurface.modelnormal3f = NULL;
7776 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7777 rsurface.modelvertexmesh = NULL;
7778 rsurface.modelvertexmeshbuffer = NULL;
7779 rsurface.modelvertex3fbuffer = NULL;
7781 rsurface.modelvertex3f_vertexbuffer = 0;
7782 rsurface.modelvertex3f_bufferoffset = 0;
7783 rsurface.modelsvector3f_vertexbuffer = 0;
7784 rsurface.modelsvector3f_bufferoffset = 0;
7785 rsurface.modeltvector3f_vertexbuffer = 0;
7786 rsurface.modeltvector3f_bufferoffset = 0;
7787 rsurface.modelnormal3f_vertexbuffer = 0;
7788 rsurface.modelnormal3f_bufferoffset = 0;
7789 rsurface.modelgeneratedvertex = true;
7793 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7794 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7795 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7796 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7797 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7798 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7799 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7800 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7801 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7802 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7803 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7804 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7805 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7806 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7807 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7808 rsurface.modelgeneratedvertex = false;
7810 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7811 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7812 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7813 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7814 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7815 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7816 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7817 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7818 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7819 rsurface.modelelement3i = model->surfmesh.data_element3i;
7820 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7821 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7822 rsurface.modelelement3s = model->surfmesh.data_element3s;
7823 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7824 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7825 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7826 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7827 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7828 rsurface.modelsurfaces = model->data_surfaces;
7829 rsurface.batchgeneratedvertex = false;
7830 rsurface.batchfirstvertex = 0;
7831 rsurface.batchnumvertices = 0;
7832 rsurface.batchfirsttriangle = 0;
7833 rsurface.batchnumtriangles = 0;
7834 rsurface.batchvertex3f = NULL;
7835 rsurface.batchvertex3f_vertexbuffer = NULL;
7836 rsurface.batchvertex3f_bufferoffset = 0;
7837 rsurface.batchsvector3f = NULL;
7838 rsurface.batchsvector3f_vertexbuffer = NULL;
7839 rsurface.batchsvector3f_bufferoffset = 0;
7840 rsurface.batchtvector3f = NULL;
7841 rsurface.batchtvector3f_vertexbuffer = NULL;
7842 rsurface.batchtvector3f_bufferoffset = 0;
7843 rsurface.batchnormal3f = NULL;
7844 rsurface.batchnormal3f_vertexbuffer = NULL;
7845 rsurface.batchnormal3f_bufferoffset = 0;
7846 rsurface.batchlightmapcolor4f = NULL;
7847 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7848 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7849 rsurface.batchtexcoordtexture2f = NULL;
7850 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7851 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7852 rsurface.batchtexcoordlightmap2f = NULL;
7853 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7854 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7855 rsurface.batchvertexmesh = NULL;
7856 rsurface.batchvertexmeshbuffer = NULL;
7857 rsurface.batchvertex3fbuffer = NULL;
7858 rsurface.batchelement3i = NULL;
7859 rsurface.batchelement3i_indexbuffer = NULL;
7860 rsurface.batchelement3i_bufferoffset = 0;
7861 rsurface.batchelement3s = NULL;
7862 rsurface.batchelement3s_indexbuffer = NULL;
7863 rsurface.batchelement3s_bufferoffset = 0;
7864 rsurface.passcolor4f = NULL;
7865 rsurface.passcolor4f_vertexbuffer = NULL;
7866 rsurface.passcolor4f_bufferoffset = 0;
7869 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)
7871 rsurface.entity = r_refdef.scene.worldentity;
7872 rsurface.skeleton = NULL;
7873 rsurface.ent_skinnum = 0;
7874 rsurface.ent_qwskin = -1;
7875 rsurface.ent_shadertime = shadertime;
7876 rsurface.ent_flags = entflags;
7877 rsurface.modelnumvertices = numvertices;
7878 rsurface.modelnumtriangles = numtriangles;
7879 rsurface.matrix = *matrix;
7880 rsurface.inversematrix = *inversematrix;
7881 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7882 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7883 R_EntityMatrix(&rsurface.matrix);
7884 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7885 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7886 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7887 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7888 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7889 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7890 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7891 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7892 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7893 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7894 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7895 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
7896 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);
7897 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7898 rsurface.frameblend[0].lerp = 1;
7899 rsurface.ent_alttextures = false;
7900 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7901 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7904 rsurface.modelvertex3f = (float *)vertex3f;
7905 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7906 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7907 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7909 else if (wantnormals)
7911 rsurface.modelvertex3f = (float *)vertex3f;
7912 rsurface.modelsvector3f = NULL;
7913 rsurface.modeltvector3f = NULL;
7914 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7918 rsurface.modelvertex3f = (float *)vertex3f;
7919 rsurface.modelsvector3f = NULL;
7920 rsurface.modeltvector3f = NULL;
7921 rsurface.modelnormal3f = NULL;
7923 rsurface.modelvertexmesh = NULL;
7924 rsurface.modelvertexmeshbuffer = NULL;
7925 rsurface.modelvertex3fbuffer = NULL;
7926 rsurface.modelvertex3f_vertexbuffer = 0;
7927 rsurface.modelvertex3f_bufferoffset = 0;
7928 rsurface.modelsvector3f_vertexbuffer = 0;
7929 rsurface.modelsvector3f_bufferoffset = 0;
7930 rsurface.modeltvector3f_vertexbuffer = 0;
7931 rsurface.modeltvector3f_bufferoffset = 0;
7932 rsurface.modelnormal3f_vertexbuffer = 0;
7933 rsurface.modelnormal3f_bufferoffset = 0;
7934 rsurface.modelgeneratedvertex = true;
7935 rsurface.modellightmapcolor4f = (float *)color4f;
7936 rsurface.modellightmapcolor4f_vertexbuffer = 0;
7937 rsurface.modellightmapcolor4f_bufferoffset = 0;
7938 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
7939 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
7940 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
7941 rsurface.modeltexcoordlightmap2f = NULL;
7942 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
7943 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
7944 rsurface.modelelement3i = (int *)element3i;
7945 rsurface.modelelement3i_indexbuffer = NULL;
7946 rsurface.modelelement3i_bufferoffset = 0;
7947 rsurface.modelelement3s = (unsigned short *)element3s;
7948 rsurface.modelelement3s_indexbuffer = NULL;
7949 rsurface.modelelement3s_bufferoffset = 0;
7950 rsurface.modellightmapoffsets = NULL;
7951 rsurface.modelsurfaces = NULL;
7952 rsurface.batchgeneratedvertex = false;
7953 rsurface.batchfirstvertex = 0;
7954 rsurface.batchnumvertices = 0;
7955 rsurface.batchfirsttriangle = 0;
7956 rsurface.batchnumtriangles = 0;
7957 rsurface.batchvertex3f = NULL;
7958 rsurface.batchvertex3f_vertexbuffer = NULL;
7959 rsurface.batchvertex3f_bufferoffset = 0;
7960 rsurface.batchsvector3f = NULL;
7961 rsurface.batchsvector3f_vertexbuffer = NULL;
7962 rsurface.batchsvector3f_bufferoffset = 0;
7963 rsurface.batchtvector3f = NULL;
7964 rsurface.batchtvector3f_vertexbuffer = NULL;
7965 rsurface.batchtvector3f_bufferoffset = 0;
7966 rsurface.batchnormal3f = NULL;
7967 rsurface.batchnormal3f_vertexbuffer = NULL;
7968 rsurface.batchnormal3f_bufferoffset = 0;
7969 rsurface.batchlightmapcolor4f = NULL;
7970 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7971 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7972 rsurface.batchtexcoordtexture2f = NULL;
7973 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7974 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7975 rsurface.batchtexcoordlightmap2f = NULL;
7976 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7977 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7978 rsurface.batchvertexmesh = NULL;
7979 rsurface.batchvertexmeshbuffer = NULL;
7980 rsurface.batchvertex3fbuffer = NULL;
7981 rsurface.batchelement3i = NULL;
7982 rsurface.batchelement3i_indexbuffer = NULL;
7983 rsurface.batchelement3i_bufferoffset = 0;
7984 rsurface.batchelement3s = NULL;
7985 rsurface.batchelement3s_indexbuffer = NULL;
7986 rsurface.batchelement3s_bufferoffset = 0;
7987 rsurface.passcolor4f = NULL;
7988 rsurface.passcolor4f_vertexbuffer = NULL;
7989 rsurface.passcolor4f_bufferoffset = 0;
7991 if (rsurface.modelnumvertices && rsurface.modelelement3i)
7993 if ((wantnormals || wanttangents) && !normal3f)
7995 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7996 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
7998 if (wanttangents && !svector3f)
8000 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8001 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8002 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8007 float RSurf_FogPoint(const float *v)
8009 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8010 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8011 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8012 float FogHeightFade = r_refdef.fogheightfade;
8014 unsigned int fogmasktableindex;
8015 if (r_refdef.fogplaneviewabove)
8016 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8018 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8019 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8020 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8023 float RSurf_FogVertex(const float *v)
8025 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8026 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8027 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8028 float FogHeightFade = rsurface.fogheightfade;
8030 unsigned int fogmasktableindex;
8031 if (r_refdef.fogplaneviewabove)
8032 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8034 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8035 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8036 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8039 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8042 for (i = 0;i < numelements;i++)
8043 outelement3i[i] = inelement3i[i] + adjust;
8046 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8047 extern cvar_t gl_vbo;
8048 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8056 int surfacefirsttriangle;
8057 int surfacenumtriangles;
8058 int surfacefirstvertex;
8059 int surfaceendvertex;
8060 int surfacenumvertices;
8061 int batchnumvertices;
8062 int batchnumtriangles;
8066 qboolean dynamicvertex;
8070 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8072 q3shaderinfo_deform_t *deform;
8073 const msurface_t *surface, *firstsurface;
8074 r_vertexmesh_t *vertexmesh;
8075 if (!texturenumsurfaces)
8077 // find vertex range of this surface batch
8079 firstsurface = texturesurfacelist[0];
8080 firsttriangle = firstsurface->num_firsttriangle;
8081 batchnumvertices = 0;
8082 batchnumtriangles = 0;
8083 firstvertex = endvertex = firstsurface->num_firstvertex;
8084 for (i = 0;i < texturenumsurfaces;i++)
8086 surface = texturesurfacelist[i];
8087 if (surface != firstsurface + i)
8089 surfacefirstvertex = surface->num_firstvertex;
8090 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8091 surfacenumvertices = surface->num_vertices;
8092 surfacenumtriangles = surface->num_triangles;
8093 if (firstvertex > surfacefirstvertex)
8094 firstvertex = surfacefirstvertex;
8095 if (endvertex < surfaceendvertex)
8096 endvertex = surfaceendvertex;
8097 batchnumvertices += surfacenumvertices;
8098 batchnumtriangles += surfacenumtriangles;
8101 // we now know the vertex range used, and if there are any gaps in it
8102 rsurface.batchfirstvertex = firstvertex;
8103 rsurface.batchnumvertices = endvertex - firstvertex;
8104 rsurface.batchfirsttriangle = firsttriangle;
8105 rsurface.batchnumtriangles = batchnumtriangles;
8107 // this variable holds flags for which properties have been updated that
8108 // may require regenerating vertexmesh array...
8111 // check if any dynamic vertex processing must occur
8112 dynamicvertex = false;
8114 // if there is a chance of animated vertex colors, it's a dynamic batch
8115 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8117 dynamicvertex = true;
8118 batchneed |= BATCHNEED_NOGAPS;
8119 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8122 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8124 switch (deform->deform)
8127 case Q3DEFORM_PROJECTIONSHADOW:
8128 case Q3DEFORM_TEXT0:
8129 case Q3DEFORM_TEXT1:
8130 case Q3DEFORM_TEXT2:
8131 case Q3DEFORM_TEXT3:
8132 case Q3DEFORM_TEXT4:
8133 case Q3DEFORM_TEXT5:
8134 case Q3DEFORM_TEXT6:
8135 case Q3DEFORM_TEXT7:
8138 case Q3DEFORM_AUTOSPRITE:
8139 dynamicvertex = true;
8140 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8141 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8143 case Q3DEFORM_AUTOSPRITE2:
8144 dynamicvertex = true;
8145 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8146 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8148 case Q3DEFORM_NORMAL:
8149 dynamicvertex = true;
8150 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8151 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8154 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8155 break; // if wavefunc is a nop, ignore this transform
8156 dynamicvertex = true;
8157 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8158 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8160 case Q3DEFORM_BULGE:
8161 dynamicvertex = true;
8162 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8163 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8166 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8167 break; // if wavefunc is a nop, ignore this transform
8168 dynamicvertex = true;
8169 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8170 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8174 switch(rsurface.texture->tcgen.tcgen)
8177 case Q3TCGEN_TEXTURE:
8179 case Q3TCGEN_LIGHTMAP:
8180 dynamicvertex = true;
8181 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8182 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8184 case Q3TCGEN_VECTOR:
8185 dynamicvertex = true;
8186 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8187 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8189 case Q3TCGEN_ENVIRONMENT:
8190 dynamicvertex = true;
8191 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8192 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8195 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8197 dynamicvertex = true;
8198 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8199 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8202 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8204 dynamicvertex = true;
8205 batchneed |= BATCHNEED_NOGAPS;
8206 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8209 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8211 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8212 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8213 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8214 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8215 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8216 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8217 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8220 // when the model data has no vertex buffer (dynamic mesh), we need to
8222 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8223 batchneed |= BATCHNEED_NOGAPS;
8225 // if needsupdate, we have to do a dynamic vertex batch for sure
8226 if (needsupdate & batchneed)
8227 dynamicvertex = true;
8229 // see if we need to build vertexmesh from arrays
8230 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8231 dynamicvertex = true;
8233 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8234 // also some drivers strongly dislike firstvertex
8235 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8236 dynamicvertex = true;
8238 rsurface.batchvertex3f = rsurface.modelvertex3f;
8239 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8240 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8241 rsurface.batchsvector3f = rsurface.modelsvector3f;
8242 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8243 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8244 rsurface.batchtvector3f = rsurface.modeltvector3f;
8245 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8246 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8247 rsurface.batchnormal3f = rsurface.modelnormal3f;
8248 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8249 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8250 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8251 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8252 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8253 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8254 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8255 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8256 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8257 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8258 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8259 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8260 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8261 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8262 rsurface.batchelement3i = rsurface.modelelement3i;
8263 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8264 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8265 rsurface.batchelement3s = rsurface.modelelement3s;
8266 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8267 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8269 // if any dynamic vertex processing has to occur in software, we copy the
8270 // entire surface list together before processing to rebase the vertices
8271 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8273 // if any gaps exist and we do not have a static vertex buffer, we have to
8274 // copy the surface list together to avoid wasting upload bandwidth on the
8275 // vertices in the gaps.
8277 // if gaps exist and we have a static vertex buffer, we still have to
8278 // combine the index buffer ranges into one dynamic index buffer.
8280 // in all cases we end up with data that can be drawn in one call.
8284 // static vertex data, just set pointers...
8285 rsurface.batchgeneratedvertex = false;
8286 // if there are gaps, we want to build a combined index buffer,
8287 // otherwise use the original static buffer with an appropriate offset
8290 // build a new triangle elements array for this batch
8291 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8292 rsurface.batchfirsttriangle = 0;
8294 for (i = 0;i < texturenumsurfaces;i++)
8296 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8297 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8298 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8299 numtriangles += surfacenumtriangles;
8301 rsurface.batchelement3i_indexbuffer = NULL;
8302 rsurface.batchelement3i_bufferoffset = 0;
8303 rsurface.batchelement3s = NULL;
8304 rsurface.batchelement3s_indexbuffer = NULL;
8305 rsurface.batchelement3s_bufferoffset = 0;
8306 if (endvertex <= 65536)
8308 // make a 16bit (unsigned short) index array if possible
8309 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8310 for (i = 0;i < numtriangles*3;i++)
8311 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8317 // something needs software processing, do it for real...
8318 // we only directly handle separate array data in this case and then
8319 // generate interleaved data if needed...
8320 rsurface.batchgeneratedvertex = true;
8322 // now copy the vertex data into a combined array and make an index array
8323 // (this is what Quake3 does all the time)
8324 //if (gaps || rsurface.batchfirstvertex)
8326 rsurface.batchvertex3fbuffer = NULL;
8327 rsurface.batchvertexmesh = NULL;
8328 rsurface.batchvertexmeshbuffer = NULL;
8329 rsurface.batchvertex3f = NULL;
8330 rsurface.batchvertex3f_vertexbuffer = NULL;
8331 rsurface.batchvertex3f_bufferoffset = 0;
8332 rsurface.batchsvector3f = NULL;
8333 rsurface.batchsvector3f_vertexbuffer = NULL;
8334 rsurface.batchsvector3f_bufferoffset = 0;
8335 rsurface.batchtvector3f = NULL;
8336 rsurface.batchtvector3f_vertexbuffer = NULL;
8337 rsurface.batchtvector3f_bufferoffset = 0;
8338 rsurface.batchnormal3f = NULL;
8339 rsurface.batchnormal3f_vertexbuffer = NULL;
8340 rsurface.batchnormal3f_bufferoffset = 0;
8341 rsurface.batchlightmapcolor4f = NULL;
8342 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8343 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8344 rsurface.batchtexcoordtexture2f = NULL;
8345 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8346 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8347 rsurface.batchtexcoordlightmap2f = NULL;
8348 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8349 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8350 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8351 rsurface.batchelement3i_indexbuffer = NULL;
8352 rsurface.batchelement3i_bufferoffset = 0;
8353 rsurface.batchelement3s = NULL;
8354 rsurface.batchelement3s_indexbuffer = NULL;
8355 rsurface.batchelement3s_bufferoffset = 0;
8356 // we'll only be setting up certain arrays as needed
8357 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8358 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8359 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8360 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8361 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8362 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8363 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8365 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8366 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8368 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8369 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8370 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8371 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8372 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8373 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8376 for (i = 0;i < texturenumsurfaces;i++)
8378 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8379 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8380 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8381 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8382 // copy only the data requested
8383 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8384 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8385 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8387 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8388 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8389 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8390 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8391 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8393 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8394 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8396 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8397 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8398 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8399 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8400 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8401 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8403 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8404 numvertices += surfacenumvertices;
8405 numtriangles += surfacenumtriangles;
8408 // generate a 16bit index array as well if possible
8409 // (in general, dynamic batches fit)
8410 if (numvertices <= 65536)
8412 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8413 for (i = 0;i < numtriangles*3;i++)
8414 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8417 // since we've copied everything, the batch now starts at 0
8418 rsurface.batchfirstvertex = 0;
8419 rsurface.batchnumvertices = batchnumvertices;
8420 rsurface.batchfirsttriangle = 0;
8421 rsurface.batchnumtriangles = batchnumtriangles;
8424 // q1bsp surfaces rendered in vertex color mode have to have colors
8425 // calculated based on lightstyles
8426 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8428 // generate color arrays for the surfaces in this list
8433 const unsigned char *lm;
8434 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8435 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8436 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8438 for (i = 0;i < texturenumsurfaces;i++)
8440 surface = texturesurfacelist[i];
8441 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8442 surfacenumvertices = surface->num_vertices;
8443 if (surface->lightmapinfo->samples)
8445 for (j = 0;j < surfacenumvertices;j++)
8447 lm = surface->lightmapinfo->samples + offsets[j];
8448 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8449 VectorScale(lm, scale, c);
8450 if (surface->lightmapinfo->styles[1] != 255)
8452 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8454 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8455 VectorMA(c, scale, lm, c);
8456 if (surface->lightmapinfo->styles[2] != 255)
8459 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8460 VectorMA(c, scale, lm, c);
8461 if (surface->lightmapinfo->styles[3] != 255)
8464 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8465 VectorMA(c, scale, lm, c);
8472 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);
8478 for (j = 0;j < surfacenumvertices;j++)
8480 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8487 // if vertices are deformed (sprite flares and things in maps, possibly
8488 // water waves, bulges and other deformations), modify the copied vertices
8490 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8492 switch (deform->deform)
8495 case Q3DEFORM_PROJECTIONSHADOW:
8496 case Q3DEFORM_TEXT0:
8497 case Q3DEFORM_TEXT1:
8498 case Q3DEFORM_TEXT2:
8499 case Q3DEFORM_TEXT3:
8500 case Q3DEFORM_TEXT4:
8501 case Q3DEFORM_TEXT5:
8502 case Q3DEFORM_TEXT6:
8503 case Q3DEFORM_TEXT7:
8506 case Q3DEFORM_AUTOSPRITE:
8507 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8508 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8509 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8510 VectorNormalize(newforward);
8511 VectorNormalize(newright);
8512 VectorNormalize(newup);
8513 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8514 // rsurface.batchvertex3f_vertexbuffer = NULL;
8515 // rsurface.batchvertex3f_bufferoffset = 0;
8516 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8517 // rsurface.batchsvector3f_vertexbuffer = NULL;
8518 // rsurface.batchsvector3f_bufferoffset = 0;
8519 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8520 // rsurface.batchtvector3f_vertexbuffer = NULL;
8521 // rsurface.batchtvector3f_bufferoffset = 0;
8522 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8523 // rsurface.batchnormal3f_vertexbuffer = NULL;
8524 // rsurface.batchnormal3f_bufferoffset = 0;
8525 // a single autosprite surface can contain multiple sprites...
8526 for (j = 0;j < batchnumvertices - 3;j += 4)
8528 VectorClear(center);
8529 for (i = 0;i < 4;i++)
8530 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8531 VectorScale(center, 0.25f, center);
8532 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8533 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8534 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8535 for (i = 0;i < 4;i++)
8537 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8538 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8541 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8542 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8543 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);
8545 case Q3DEFORM_AUTOSPRITE2:
8546 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8547 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8548 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8549 VectorNormalize(newforward);
8550 VectorNormalize(newright);
8551 VectorNormalize(newup);
8552 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8553 // rsurface.batchvertex3f_vertexbuffer = NULL;
8554 // rsurface.batchvertex3f_bufferoffset = 0;
8556 const float *v1, *v2;
8566 memset(shortest, 0, sizeof(shortest));
8567 // a single autosprite surface can contain multiple sprites...
8568 for (j = 0;j < batchnumvertices - 3;j += 4)
8570 VectorClear(center);
8571 for (i = 0;i < 4;i++)
8572 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8573 VectorScale(center, 0.25f, center);
8574 // find the two shortest edges, then use them to define the
8575 // axis vectors for rotating around the central axis
8576 for (i = 0;i < 6;i++)
8578 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8579 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8580 l = VectorDistance2(v1, v2);
8581 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8583 l += (1.0f / 1024.0f);
8584 if (shortest[0].length2 > l || i == 0)
8586 shortest[1] = shortest[0];
8587 shortest[0].length2 = l;
8588 shortest[0].v1 = v1;
8589 shortest[0].v2 = v2;
8591 else if (shortest[1].length2 > l || i == 1)
8593 shortest[1].length2 = l;
8594 shortest[1].v1 = v1;
8595 shortest[1].v2 = v2;
8598 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8599 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8600 // this calculates the right vector from the shortest edge
8601 // and the up vector from the edge midpoints
8602 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8603 VectorNormalize(right);
8604 VectorSubtract(end, start, up);
8605 VectorNormalize(up);
8606 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8607 VectorSubtract(rsurface.localvieworigin, center, forward);
8608 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8609 VectorNegate(forward, forward);
8610 VectorReflect(forward, 0, up, forward);
8611 VectorNormalize(forward);
8612 CrossProduct(up, forward, newright);
8613 VectorNormalize(newright);
8614 // rotate the quad around the up axis vector, this is made
8615 // especially easy by the fact we know the quad is flat,
8616 // so we only have to subtract the center position and
8617 // measure distance along the right vector, and then
8618 // multiply that by the newright vector and add back the
8620 // we also need to subtract the old position to undo the
8621 // displacement from the center, which we do with a
8622 // DotProduct, the subtraction/addition of center is also
8623 // optimized into DotProducts here
8624 l = DotProduct(right, center);
8625 for (i = 0;i < 4;i++)
8627 v1 = rsurface.batchvertex3f + 3*(j+i);
8628 f = DotProduct(right, v1) - l;
8629 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8633 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8635 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8636 // rsurface.batchnormal3f_vertexbuffer = NULL;
8637 // rsurface.batchnormal3f_bufferoffset = 0;
8638 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8640 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8642 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8643 // rsurface.batchsvector3f_vertexbuffer = NULL;
8644 // rsurface.batchsvector3f_bufferoffset = 0;
8645 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8646 // rsurface.batchtvector3f_vertexbuffer = NULL;
8647 // rsurface.batchtvector3f_bufferoffset = 0;
8648 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);
8651 case Q3DEFORM_NORMAL:
8652 // deform the normals to make reflections wavey
8653 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8654 rsurface.batchnormal3f_vertexbuffer = NULL;
8655 rsurface.batchnormal3f_bufferoffset = 0;
8656 for (j = 0;j < batchnumvertices;j++)
8659 float *normal = rsurface.batchnormal3f + 3*j;
8660 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8661 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8662 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]);
8663 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]);
8664 VectorNormalize(normal);
8666 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8668 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8669 // rsurface.batchsvector3f_vertexbuffer = NULL;
8670 // rsurface.batchsvector3f_bufferoffset = 0;
8671 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8672 // rsurface.batchtvector3f_vertexbuffer = NULL;
8673 // rsurface.batchtvector3f_bufferoffset = 0;
8674 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
8678 // deform vertex array to make wavey water and flags and such
8679 waveparms[0] = deform->waveparms[0];
8680 waveparms[1] = deform->waveparms[1];
8681 waveparms[2] = deform->waveparms[2];
8682 waveparms[3] = deform->waveparms[3];
8683 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8684 break; // if wavefunc is a nop, don't make a dynamic vertex array
8685 // this is how a divisor of vertex influence on deformation
8686 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8687 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8688 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8689 // rsurface.batchvertex3f_vertexbuffer = NULL;
8690 // rsurface.batchvertex3f_bufferoffset = 0;
8691 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8692 // rsurface.batchnormal3f_vertexbuffer = NULL;
8693 // rsurface.batchnormal3f_bufferoffset = 0;
8694 for (j = 0;j < batchnumvertices;j++)
8696 // if the wavefunc depends on time, evaluate it per-vertex
8699 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8700 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8702 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8704 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8705 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8706 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8708 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8709 // rsurface.batchsvector3f_vertexbuffer = NULL;
8710 // rsurface.batchsvector3f_bufferoffset = 0;
8711 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8712 // rsurface.batchtvector3f_vertexbuffer = NULL;
8713 // rsurface.batchtvector3f_bufferoffset = 0;
8714 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);
8717 case Q3DEFORM_BULGE:
8718 // deform vertex array to make the surface have moving bulges
8719 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8720 // rsurface.batchvertex3f_vertexbuffer = NULL;
8721 // rsurface.batchvertex3f_bufferoffset = 0;
8722 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8723 // rsurface.batchnormal3f_vertexbuffer = NULL;
8724 // rsurface.batchnormal3f_bufferoffset = 0;
8725 for (j = 0;j < batchnumvertices;j++)
8727 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8728 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8730 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8731 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8732 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8734 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8735 // rsurface.batchsvector3f_vertexbuffer = NULL;
8736 // rsurface.batchsvector3f_bufferoffset = 0;
8737 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8738 // rsurface.batchtvector3f_vertexbuffer = NULL;
8739 // rsurface.batchtvector3f_bufferoffset = 0;
8740 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);
8744 // deform vertex array
8745 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8746 break; // if wavefunc is a nop, don't make a dynamic vertex array
8747 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8748 VectorScale(deform->parms, scale, waveparms);
8749 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8750 // rsurface.batchvertex3f_vertexbuffer = NULL;
8751 // rsurface.batchvertex3f_bufferoffset = 0;
8752 for (j = 0;j < batchnumvertices;j++)
8753 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8758 // generate texcoords based on the chosen texcoord source
8759 switch(rsurface.texture->tcgen.tcgen)
8762 case Q3TCGEN_TEXTURE:
8764 case Q3TCGEN_LIGHTMAP:
8765 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8766 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8767 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8768 if (rsurface.batchtexcoordlightmap2f)
8769 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8771 case Q3TCGEN_VECTOR:
8772 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8773 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8774 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8775 for (j = 0;j < batchnumvertices;j++)
8777 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8778 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8781 case Q3TCGEN_ENVIRONMENT:
8782 // make environment reflections using a spheremap
8783 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8784 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8785 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8786 for (j = 0;j < batchnumvertices;j++)
8788 // identical to Q3A's method, but executed in worldspace so
8789 // carried models can be shiny too
8791 float viewer[3], d, reflected[3], worldreflected[3];
8793 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8794 // VectorNormalize(viewer);
8796 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8798 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8799 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8800 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8801 // note: this is proportinal to viewer, so we can normalize later
8803 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8804 VectorNormalize(worldreflected);
8806 // note: this sphere map only uses world x and z!
8807 // so positive and negative y will LOOK THE SAME.
8808 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8809 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8813 // the only tcmod that needs software vertex processing is turbulent, so
8814 // check for it here and apply the changes if needed
8815 // and we only support that as the first one
8816 // (handling a mixture of turbulent and other tcmods would be problematic
8817 // without punting it entirely to a software path)
8818 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8820 amplitude = rsurface.texture->tcmods[0].parms[1];
8821 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8822 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8823 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8824 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8825 for (j = 0;j < batchnumvertices;j++)
8827 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);
8828 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8832 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8834 // convert the modified arrays to vertex structs
8835 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8836 // rsurface.batchvertexmeshbuffer = NULL;
8837 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8838 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8839 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8840 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8841 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8842 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
8843 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
8845 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8847 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
8848 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
8851 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
8852 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8853 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
8854 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
8855 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8856 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
8857 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
8858 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8859 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
8863 void RSurf_DrawBatch(void)
8865 // sometimes a zero triangle surface (usually a degenerate patch) makes it
8866 // through the pipeline, killing it earlier in the pipeline would have
8867 // per-surface overhead rather than per-batch overhead, so it's best to
8868 // reject it here, before it hits glDraw.
8869 if (rsurface.batchnumtriangles == 0)
8872 // batch debugging code
8873 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
8879 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
8880 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
8883 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
8885 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
8887 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
8888 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);
8895 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);
8898 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
8900 // pick the closest matching water plane
8901 int planeindex, vertexindex, bestplaneindex = -1;
8905 r_waterstate_waterplane_t *p;
8906 qboolean prepared = false;
8908 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8910 if(p->camera_entity != rsurface.texture->camera_entity)
8915 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
8917 if(rsurface.batchnumvertices == 0)
8920 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
8922 Matrix4x4_Transform(&rsurface.matrix, v, vert);
8923 d += fabs(PlaneDiff(vert, &p->plane));
8925 if (bestd > d || bestplaneindex < 0)
8928 bestplaneindex = planeindex;
8931 return bestplaneindex;
8932 // NOTE: this MAY return a totally unrelated water plane; we can ignore
8933 // this situation though, as it might be better to render single larger
8934 // batches with useless stuff (backface culled for example) than to
8935 // render multiple smaller batches
8938 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
8941 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8942 rsurface.passcolor4f_vertexbuffer = 0;
8943 rsurface.passcolor4f_bufferoffset = 0;
8944 for (i = 0;i < rsurface.batchnumvertices;i++)
8945 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
8948 static void RSurf_DrawBatch_GL11_ApplyFog(void)
8955 if (rsurface.passcolor4f)
8957 // generate color arrays
8958 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8959 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8960 rsurface.passcolor4f_vertexbuffer = 0;
8961 rsurface.passcolor4f_bufferoffset = 0;
8962 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)
8964 f = RSurf_FogVertex(v);
8973 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8974 rsurface.passcolor4f_vertexbuffer = 0;
8975 rsurface.passcolor4f_bufferoffset = 0;
8976 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
8978 f = RSurf_FogVertex(v);
8987 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
8994 if (!rsurface.passcolor4f)
8996 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8997 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8998 rsurface.passcolor4f_vertexbuffer = 0;
8999 rsurface.passcolor4f_bufferoffset = 0;
9000 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)
9002 f = RSurf_FogVertex(v);
9003 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9004 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9005 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9010 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9015 if (!rsurface.passcolor4f)
9017 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9018 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9019 rsurface.passcolor4f_vertexbuffer = 0;
9020 rsurface.passcolor4f_bufferoffset = 0;
9021 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9030 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9035 if (!rsurface.passcolor4f)
9037 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9038 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9039 rsurface.passcolor4f_vertexbuffer = 0;
9040 rsurface.passcolor4f_bufferoffset = 0;
9041 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9043 c2[0] = c[0] + r_refdef.scene.ambient;
9044 c2[1] = c[1] + r_refdef.scene.ambient;
9045 c2[2] = c[2] + r_refdef.scene.ambient;
9050 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9053 rsurface.passcolor4f = NULL;
9054 rsurface.passcolor4f_vertexbuffer = 0;
9055 rsurface.passcolor4f_bufferoffset = 0;
9056 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9057 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9058 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9059 GL_Color(r, g, b, a);
9060 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9064 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9066 // TODO: optimize applyfog && applycolor case
9067 // just apply fog if necessary, and tint the fog color array if necessary
9068 rsurface.passcolor4f = NULL;
9069 rsurface.passcolor4f_vertexbuffer = 0;
9070 rsurface.passcolor4f_bufferoffset = 0;
9071 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9072 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9073 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9074 GL_Color(r, g, b, a);
9078 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9081 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9082 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9083 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9084 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9085 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9086 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9087 GL_Color(r, g, b, a);
9091 static void RSurf_DrawBatch_GL11_ClampColor(void)
9096 if (!rsurface.passcolor4f)
9098 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9100 c2[0] = bound(0.0f, c1[0], 1.0f);
9101 c2[1] = bound(0.0f, c1[1], 1.0f);
9102 c2[2] = bound(0.0f, c1[2], 1.0f);
9103 c2[3] = bound(0.0f, c1[3], 1.0f);
9107 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9117 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9118 rsurface.passcolor4f_vertexbuffer = 0;
9119 rsurface.passcolor4f_bufferoffset = 0;
9120 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)
9122 f = -DotProduct(r_refdef.view.forward, n);
9124 f = f * 0.85 + 0.15; // work around so stuff won't get black
9125 f *= r_refdef.lightmapintensity;
9126 Vector4Set(c, f, f, f, 1);
9130 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9132 RSurf_DrawBatch_GL11_ApplyFakeLight();
9133 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9134 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9135 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9136 GL_Color(r, g, b, a);
9140 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9148 vec3_t ambientcolor;
9149 vec3_t diffusecolor;
9153 VectorCopy(rsurface.modellight_lightdir, lightdir);
9154 f = 0.5f * r_refdef.lightmapintensity;
9155 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9156 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9157 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9158 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9159 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9160 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9162 if (VectorLength2(diffusecolor) > 0)
9164 // q3-style directional shading
9165 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9166 rsurface.passcolor4f_vertexbuffer = 0;
9167 rsurface.passcolor4f_bufferoffset = 0;
9168 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)
9170 if ((f = DotProduct(n, lightdir)) > 0)
9171 VectorMA(ambientcolor, f, diffusecolor, c);
9173 VectorCopy(ambientcolor, c);
9180 *applycolor = false;
9184 *r = ambientcolor[0];
9185 *g = ambientcolor[1];
9186 *b = ambientcolor[2];
9187 rsurface.passcolor4f = NULL;
9188 rsurface.passcolor4f_vertexbuffer = 0;
9189 rsurface.passcolor4f_bufferoffset = 0;
9193 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9195 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9196 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9197 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9198 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9199 GL_Color(r, g, b, a);
9203 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9211 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9212 rsurface.passcolor4f_vertexbuffer = 0;
9213 rsurface.passcolor4f_bufferoffset = 0;
9215 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9217 f = 1 - RSurf_FogVertex(v);
9225 void RSurf_SetupDepthAndCulling(void)
9227 // submodels are biased to avoid z-fighting with world surfaces that they
9228 // may be exactly overlapping (avoids z-fighting artifacts on certain
9229 // doors and things in Quake maps)
9230 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9231 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9232 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9233 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9236 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9238 // transparent sky would be ridiculous
9239 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9241 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9242 skyrenderlater = true;
9243 RSurf_SetupDepthAndCulling();
9245 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9246 // skymasking on them, and Quake3 never did sky masking (unlike
9247 // software Quake and software Quake2), so disable the sky masking
9248 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9249 // and skymasking also looks very bad when noclipping outside the
9250 // level, so don't use it then either.
9251 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9253 R_Mesh_ResetTextureState();
9254 if (skyrendermasked)
9256 R_SetupShader_DepthOrShadow();
9257 // depth-only (masking)
9258 GL_ColorMask(0,0,0,0);
9259 // just to make sure that braindead drivers don't draw
9260 // anything despite that colormask...
9261 GL_BlendFunc(GL_ZERO, GL_ONE);
9262 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9263 if (rsurface.batchvertex3fbuffer)
9264 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9266 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9270 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9272 GL_BlendFunc(GL_ONE, GL_ZERO);
9273 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9274 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9275 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9278 if (skyrendermasked)
9279 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9281 R_Mesh_ResetTextureState();
9282 GL_Color(1, 1, 1, 1);
9285 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9286 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9287 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9289 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9293 // render screenspace normalmap to texture
9295 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9300 // bind lightmap texture
9302 // water/refraction/reflection/camera surfaces have to be handled specially
9303 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9305 int start, end, startplaneindex;
9306 for (start = 0;start < texturenumsurfaces;start = end)
9308 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9309 if(startplaneindex < 0)
9311 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9312 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9316 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9318 // now that we have a batch using the same planeindex, render it
9319 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9321 // render water or distortion background
9323 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));
9325 // blend surface on top
9326 GL_DepthMask(false);
9327 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9330 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9332 // render surface with reflection texture as input
9333 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9334 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));
9341 // render surface batch normally
9342 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9343 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9347 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9349 // OpenGL 1.3 path - anything not completely ancient
9350 qboolean applycolor;
9353 const texturelayer_t *layer;
9354 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);
9355 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9357 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9360 int layertexrgbscale;
9361 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9363 if (layerindex == 0)
9367 GL_AlphaTest(false);
9368 GL_DepthFunc(GL_EQUAL);
9371 GL_DepthMask(layer->depthmask && writedepth);
9372 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9373 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9375 layertexrgbscale = 4;
9376 VectorScale(layer->color, 0.25f, layercolor);
9378 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9380 layertexrgbscale = 2;
9381 VectorScale(layer->color, 0.5f, layercolor);
9385 layertexrgbscale = 1;
9386 VectorScale(layer->color, 1.0f, layercolor);
9388 layercolor[3] = layer->color[3];
9389 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9390 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9391 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9392 switch (layer->type)
9394 case TEXTURELAYERTYPE_LITTEXTURE:
9395 // single-pass lightmapped texture with 2x rgbscale
9396 R_Mesh_TexBind(0, r_texture_white);
9397 R_Mesh_TexMatrix(0, NULL);
9398 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9399 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9400 R_Mesh_TexBind(1, layer->texture);
9401 R_Mesh_TexMatrix(1, &layer->texmatrix);
9402 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9403 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9404 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9405 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9406 else if (FAKELIGHT_ENABLED)
9407 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9408 else if (rsurface.uselightmaptexture)
9409 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9411 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9413 case TEXTURELAYERTYPE_TEXTURE:
9414 // singletexture unlit texture with transparency support
9415 R_Mesh_TexBind(0, layer->texture);
9416 R_Mesh_TexMatrix(0, &layer->texmatrix);
9417 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9418 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9419 R_Mesh_TexBind(1, 0);
9420 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9421 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9423 case TEXTURELAYERTYPE_FOG:
9424 // singletexture fogging
9427 R_Mesh_TexBind(0, layer->texture);
9428 R_Mesh_TexMatrix(0, &layer->texmatrix);
9429 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9430 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9434 R_Mesh_TexBind(0, 0);
9435 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9437 R_Mesh_TexBind(1, 0);
9438 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9439 // generate a color array for the fog pass
9440 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9441 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9445 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9448 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9450 GL_DepthFunc(GL_LEQUAL);
9451 GL_AlphaTest(false);
9455 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9457 // OpenGL 1.1 - crusty old voodoo path
9460 const texturelayer_t *layer;
9461 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);
9462 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9464 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9466 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9468 if (layerindex == 0)
9472 GL_AlphaTest(false);
9473 GL_DepthFunc(GL_EQUAL);
9476 GL_DepthMask(layer->depthmask && writedepth);
9477 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9478 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9479 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9480 switch (layer->type)
9482 case TEXTURELAYERTYPE_LITTEXTURE:
9483 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9485 // two-pass lit texture with 2x rgbscale
9486 // first the lightmap pass
9487 R_Mesh_TexBind(0, r_texture_white);
9488 R_Mesh_TexMatrix(0, NULL);
9489 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9490 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9491 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9492 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9493 else if (FAKELIGHT_ENABLED)
9494 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9495 else if (rsurface.uselightmaptexture)
9496 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9498 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9499 // then apply the texture to it
9500 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9501 R_Mesh_TexBind(0, layer->texture);
9502 R_Mesh_TexMatrix(0, &layer->texmatrix);
9503 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9504 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9505 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);
9509 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9510 R_Mesh_TexBind(0, layer->texture);
9511 R_Mesh_TexMatrix(0, &layer->texmatrix);
9512 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9513 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9514 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9515 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);
9517 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);
9520 case TEXTURELAYERTYPE_TEXTURE:
9521 // singletexture unlit texture with transparency support
9522 R_Mesh_TexBind(0, layer->texture);
9523 R_Mesh_TexMatrix(0, &layer->texmatrix);
9524 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9525 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9526 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);
9528 case TEXTURELAYERTYPE_FOG:
9529 // singletexture fogging
9532 R_Mesh_TexBind(0, layer->texture);
9533 R_Mesh_TexMatrix(0, &layer->texmatrix);
9534 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9535 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9539 R_Mesh_TexBind(0, 0);
9540 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9542 // generate a color array for the fog pass
9543 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9544 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9548 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9551 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9553 GL_DepthFunc(GL_LEQUAL);
9554 GL_AlphaTest(false);
9558 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9562 r_vertexgeneric_t *batchvertex;
9565 // R_Mesh_ResetTextureState();
9566 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9568 if(rsurface.texture && rsurface.texture->currentskinframe)
9570 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9571 c[3] *= rsurface.texture->currentalpha;
9581 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9583 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9584 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9585 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9588 // brighten it up (as texture value 127 means "unlit")
9589 c[0] *= 2 * r_refdef.view.colorscale;
9590 c[1] *= 2 * r_refdef.view.colorscale;
9591 c[2] *= 2 * r_refdef.view.colorscale;
9593 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9594 c[3] *= r_wateralpha.value;
9596 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9598 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9599 GL_DepthMask(false);
9601 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9603 GL_BlendFunc(GL_ONE, GL_ONE);
9604 GL_DepthMask(false);
9606 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9608 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9609 GL_DepthMask(false);
9611 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9613 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9614 GL_DepthMask(false);
9618 GL_BlendFunc(GL_ONE, GL_ZERO);
9619 GL_DepthMask(writedepth);
9622 if (r_showsurfaces.integer == 3)
9624 rsurface.passcolor4f = NULL;
9626 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9628 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9630 rsurface.passcolor4f = NULL;
9631 rsurface.passcolor4f_vertexbuffer = 0;
9632 rsurface.passcolor4f_bufferoffset = 0;
9634 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9636 qboolean applycolor = true;
9639 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9641 r_refdef.lightmapintensity = 1;
9642 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9643 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9645 else if (FAKELIGHT_ENABLED)
9647 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9649 r_refdef.lightmapintensity = r_fakelight_intensity.value;
9650 RSurf_DrawBatch_GL11_ApplyFakeLight();
9651 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9655 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9657 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9658 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9659 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9662 if(!rsurface.passcolor4f)
9663 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9665 RSurf_DrawBatch_GL11_ApplyAmbient();
9666 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9667 if(r_refdef.fogenabled)
9668 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9669 RSurf_DrawBatch_GL11_ClampColor();
9671 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9672 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9675 else if (!r_refdef.view.showdebug)
9677 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9678 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9679 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9681 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9682 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9684 R_Mesh_PrepareVertices_Generic_Unlock();
9687 else if (r_showsurfaces.integer == 4)
9689 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9690 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9691 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9693 unsigned char c = (vi << 3) * (1.0f / 256.0f);
9694 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9695 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9697 R_Mesh_PrepareVertices_Generic_Unlock();
9700 else if (r_showsurfaces.integer == 2)
9703 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9704 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9705 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9707 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9708 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9709 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9710 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9711 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9712 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9713 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9715 R_Mesh_PrepareVertices_Generic_Unlock();
9716 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9720 int texturesurfaceindex;
9722 const msurface_t *surface;
9723 float surfacecolor4f[4];
9724 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9725 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9727 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9729 surface = texturesurfacelist[texturesurfaceindex];
9730 k = (int)(((size_t)surface) / sizeof(msurface_t));
9731 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9732 for (j = 0;j < surface->num_vertices;j++)
9734 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9735 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9739 R_Mesh_PrepareVertices_Generic_Unlock();
9744 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9747 RSurf_SetupDepthAndCulling();
9748 if (r_showsurfaces.integer)
9750 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9753 switch (vid.renderpath)
9755 case RENDERPATH_GL20:
9756 case RENDERPATH_D3D9:
9757 case RENDERPATH_D3D10:
9758 case RENDERPATH_D3D11:
9759 case RENDERPATH_SOFT:
9760 case RENDERPATH_GLES2:
9761 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9763 case RENDERPATH_GL13:
9764 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9766 case RENDERPATH_GL11:
9767 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9773 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9776 RSurf_SetupDepthAndCulling();
9777 if (r_showsurfaces.integer)
9779 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9782 switch (vid.renderpath)
9784 case RENDERPATH_GL20:
9785 case RENDERPATH_D3D9:
9786 case RENDERPATH_D3D10:
9787 case RENDERPATH_D3D11:
9788 case RENDERPATH_SOFT:
9789 case RENDERPATH_GLES2:
9790 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9792 case RENDERPATH_GL13:
9793 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9795 case RENDERPATH_GL11:
9796 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9802 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9805 int texturenumsurfaces, endsurface;
9807 const msurface_t *surface;
9808 #define MAXBATCH_TRANSPARENTSURFACES 256
9809 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9811 // if the model is static it doesn't matter what value we give for
9812 // wantnormals and wanttangents, so this logic uses only rules applicable
9813 // to a model, knowing that they are meaningless otherwise
9814 if (ent == r_refdef.scene.worldentity)
9815 RSurf_ActiveWorldEntity();
9816 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9817 RSurf_ActiveModelEntity(ent, false, false, false);
9820 switch (vid.renderpath)
9822 case RENDERPATH_GL20:
9823 case RENDERPATH_D3D9:
9824 case RENDERPATH_D3D10:
9825 case RENDERPATH_D3D11:
9826 case RENDERPATH_SOFT:
9827 case RENDERPATH_GLES2:
9828 RSurf_ActiveModelEntity(ent, true, true, false);
9830 case RENDERPATH_GL13:
9831 case RENDERPATH_GL11:
9832 RSurf_ActiveModelEntity(ent, true, false, false);
9837 if (r_transparentdepthmasking.integer)
9839 qboolean setup = false;
9840 for (i = 0;i < numsurfaces;i = j)
9843 surface = rsurface.modelsurfaces + surfacelist[i];
9844 texture = surface->texture;
9845 rsurface.texture = R_GetCurrentTexture(texture);
9846 rsurface.lightmaptexture = NULL;
9847 rsurface.deluxemaptexture = NULL;
9848 rsurface.uselightmaptexture = false;
9849 // scan ahead until we find a different texture
9850 endsurface = min(i + 1024, numsurfaces);
9851 texturenumsurfaces = 0;
9852 texturesurfacelist[texturenumsurfaces++] = surface;
9853 for (;j < endsurface;j++)
9855 surface = rsurface.modelsurfaces + surfacelist[j];
9856 if (texture != surface->texture)
9858 texturesurfacelist[texturenumsurfaces++] = surface;
9860 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9862 // render the range of surfaces as depth
9866 GL_ColorMask(0,0,0,0);
9869 GL_BlendFunc(GL_ONE, GL_ZERO);
9871 // R_Mesh_ResetTextureState();
9872 R_SetupShader_DepthOrShadow();
9874 RSurf_SetupDepthAndCulling();
9875 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9876 if (rsurface.batchvertex3fbuffer)
9877 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9879 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9883 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9886 for (i = 0;i < numsurfaces;i = j)
9889 surface = rsurface.modelsurfaces + surfacelist[i];
9890 texture = surface->texture;
9891 rsurface.texture = R_GetCurrentTexture(texture);
9892 // scan ahead until we find a different texture
9893 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
9894 texturenumsurfaces = 0;
9895 texturesurfacelist[texturenumsurfaces++] = surface;
9896 if(FAKELIGHT_ENABLED)
9898 rsurface.lightmaptexture = NULL;
9899 rsurface.deluxemaptexture = NULL;
9900 rsurface.uselightmaptexture = false;
9901 for (;j < endsurface;j++)
9903 surface = rsurface.modelsurfaces + surfacelist[j];
9904 if (texture != surface->texture)
9906 texturesurfacelist[texturenumsurfaces++] = surface;
9911 rsurface.lightmaptexture = surface->lightmaptexture;
9912 rsurface.deluxemaptexture = surface->deluxemaptexture;
9913 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
9914 for (;j < endsurface;j++)
9916 surface = rsurface.modelsurfaces + surfacelist[j];
9917 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
9919 texturesurfacelist[texturenumsurfaces++] = surface;
9922 // render the range of surfaces
9923 if (ent == r_refdef.scene.worldentity)
9924 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9926 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9928 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9931 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
9933 // transparent surfaces get pushed off into the transparent queue
9934 int surfacelistindex;
9935 const msurface_t *surface;
9936 vec3_t tempcenter, center;
9937 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
9939 surface = texturesurfacelist[surfacelistindex];
9940 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
9941 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
9942 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
9943 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
9944 if (queueentity->transparent_offset) // transparent offset
9946 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
9947 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
9948 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
9950 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
9954 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9956 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
9958 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
9960 RSurf_SetupDepthAndCulling();
9961 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9962 if (rsurface.batchvertex3fbuffer)
9963 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9965 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9969 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
9971 const entity_render_t *queueentity = r_refdef.scene.worldentity;
9974 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
9977 if (!rsurface.texture->currentnumlayers)
9979 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9980 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9982 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9984 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
9985 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
9986 else if (!rsurface.texture->currentnumlayers)
9988 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
9990 // in the deferred case, transparent surfaces were queued during prepass
9991 if (!r_shadow_usingdeferredprepass)
9992 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9996 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
9997 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10002 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10005 texture_t *texture;
10006 R_FrameData_SetMark();
10007 // break the surface list down into batches by texture and use of lightmapping
10008 for (i = 0;i < numsurfaces;i = j)
10011 // texture is the base texture pointer, rsurface.texture is the
10012 // current frame/skin the texture is directing us to use (for example
10013 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10014 // use skin 1 instead)
10015 texture = surfacelist[i]->texture;
10016 rsurface.texture = R_GetCurrentTexture(texture);
10017 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10019 // if this texture is not the kind we want, skip ahead to the next one
10020 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10024 if(FAKELIGHT_ENABLED || depthonly || prepass)
10026 rsurface.lightmaptexture = NULL;
10027 rsurface.deluxemaptexture = NULL;
10028 rsurface.uselightmaptexture = false;
10029 // simply scan ahead until we find a different texture or lightmap state
10030 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10035 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10036 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10037 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10038 // simply scan ahead until we find a different texture or lightmap state
10039 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10042 // render the range of surfaces
10043 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10045 R_FrameData_ReturnToMark();
10048 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10052 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10055 if (!rsurface.texture->currentnumlayers)
10057 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10058 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10060 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10062 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10063 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10064 else if (!rsurface.texture->currentnumlayers)
10066 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10068 // in the deferred case, transparent surfaces were queued during prepass
10069 if (!r_shadow_usingdeferredprepass)
10070 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10074 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10075 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10080 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10083 texture_t *texture;
10084 R_FrameData_SetMark();
10085 // break the surface list down into batches by texture and use of lightmapping
10086 for (i = 0;i < numsurfaces;i = j)
10089 // texture is the base texture pointer, rsurface.texture is the
10090 // current frame/skin the texture is directing us to use (for example
10091 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10092 // use skin 1 instead)
10093 texture = surfacelist[i]->texture;
10094 rsurface.texture = R_GetCurrentTexture(texture);
10095 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10097 // if this texture is not the kind we want, skip ahead to the next one
10098 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10102 if(FAKELIGHT_ENABLED || depthonly || prepass)
10104 rsurface.lightmaptexture = NULL;
10105 rsurface.deluxemaptexture = NULL;
10106 rsurface.uselightmaptexture = false;
10107 // simply scan ahead until we find a different texture or lightmap state
10108 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10113 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10114 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10115 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10116 // simply scan ahead until we find a different texture or lightmap state
10117 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10120 // render the range of surfaces
10121 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10123 R_FrameData_ReturnToMark();
10126 float locboxvertex3f[6*4*3] =
10128 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10129 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10130 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10131 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10132 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10133 1,0,0, 0,0,0, 0,1,0, 1,1,0
10136 unsigned short locboxelements[6*2*3] =
10141 12,13,14, 12,14,15,
10142 16,17,18, 16,18,19,
10146 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10149 cl_locnode_t *loc = (cl_locnode_t *)ent;
10151 float vertex3f[6*4*3];
10153 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10154 GL_DepthMask(false);
10155 GL_DepthRange(0, 1);
10156 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10157 GL_DepthTest(true);
10158 GL_CullFace(GL_NONE);
10159 R_EntityMatrix(&identitymatrix);
10161 // R_Mesh_ResetTextureState();
10163 i = surfacelist[0];
10164 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10165 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10166 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10167 surfacelist[0] < 0 ? 0.5f : 0.125f);
10169 if (VectorCompare(loc->mins, loc->maxs))
10171 VectorSet(size, 2, 2, 2);
10172 VectorMA(loc->mins, -0.5f, size, mins);
10176 VectorCopy(loc->mins, mins);
10177 VectorSubtract(loc->maxs, loc->mins, size);
10180 for (i = 0;i < 6*4*3;)
10181 for (j = 0;j < 3;j++, i++)
10182 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10184 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10185 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10186 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10189 void R_DrawLocs(void)
10192 cl_locnode_t *loc, *nearestloc;
10194 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10195 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10197 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10198 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10202 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10204 if (decalsystem->decals)
10205 Mem_Free(decalsystem->decals);
10206 memset(decalsystem, 0, sizeof(*decalsystem));
10209 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)
10212 tridecal_t *decals;
10215 // expand or initialize the system
10216 if (decalsystem->maxdecals <= decalsystem->numdecals)
10218 decalsystem_t old = *decalsystem;
10219 qboolean useshortelements;
10220 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10221 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10222 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)));
10223 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10224 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10225 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10226 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10227 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10228 if (decalsystem->numdecals)
10229 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10231 Mem_Free(old.decals);
10232 for (i = 0;i < decalsystem->maxdecals*3;i++)
10233 decalsystem->element3i[i] = i;
10234 if (useshortelements)
10235 for (i = 0;i < decalsystem->maxdecals*3;i++)
10236 decalsystem->element3s[i] = i;
10239 // grab a decal and search for another free slot for the next one
10240 decals = decalsystem->decals;
10241 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10242 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10244 decalsystem->freedecal = i;
10245 if (decalsystem->numdecals <= i)
10246 decalsystem->numdecals = i + 1;
10248 // initialize the decal
10250 decal->triangleindex = triangleindex;
10251 decal->surfaceindex = surfaceindex;
10252 decal->decalsequence = decalsequence;
10253 decal->color4f[0][0] = c0[0];
10254 decal->color4f[0][1] = c0[1];
10255 decal->color4f[0][2] = c0[2];
10256 decal->color4f[0][3] = 1;
10257 decal->color4f[1][0] = c1[0];
10258 decal->color4f[1][1] = c1[1];
10259 decal->color4f[1][2] = c1[2];
10260 decal->color4f[1][3] = 1;
10261 decal->color4f[2][0] = c2[0];
10262 decal->color4f[2][1] = c2[1];
10263 decal->color4f[2][2] = c2[2];
10264 decal->color4f[2][3] = 1;
10265 decal->vertex3f[0][0] = v0[0];
10266 decal->vertex3f[0][1] = v0[1];
10267 decal->vertex3f[0][2] = v0[2];
10268 decal->vertex3f[1][0] = v1[0];
10269 decal->vertex3f[1][1] = v1[1];
10270 decal->vertex3f[1][2] = v1[2];
10271 decal->vertex3f[2][0] = v2[0];
10272 decal->vertex3f[2][1] = v2[1];
10273 decal->vertex3f[2][2] = v2[2];
10274 decal->texcoord2f[0][0] = t0[0];
10275 decal->texcoord2f[0][1] = t0[1];
10276 decal->texcoord2f[1][0] = t1[0];
10277 decal->texcoord2f[1][1] = t1[1];
10278 decal->texcoord2f[2][0] = t2[0];
10279 decal->texcoord2f[2][1] = t2[1];
10282 extern cvar_t cl_decals_bias;
10283 extern cvar_t cl_decals_models;
10284 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10285 // baseparms, parms, temps
10286 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)
10291 const float *vertex3f;
10292 const float *normal3f;
10294 float points[2][9][3];
10301 e = rsurface.modelelement3i + 3*triangleindex;
10303 vertex3f = rsurface.modelvertex3f;
10304 normal3f = rsurface.modelnormal3f;
10308 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10310 index = 3*e[cornerindex];
10311 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10316 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10318 index = 3*e[cornerindex];
10319 VectorCopy(vertex3f + index, v[cornerindex]);
10324 //TriangleNormal(v[0], v[1], v[2], normal);
10325 //if (DotProduct(normal, localnormal) < 0.0f)
10327 // clip by each of the box planes formed from the projection matrix
10328 // if anything survives, we emit the decal
10329 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]);
10332 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]);
10335 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]);
10338 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]);
10341 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]);
10344 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]);
10347 // some part of the triangle survived, so we have to accept it...
10350 // dynamic always uses the original triangle
10352 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10354 index = 3*e[cornerindex];
10355 VectorCopy(vertex3f + index, v[cornerindex]);
10358 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10360 // convert vertex positions to texcoords
10361 Matrix4x4_Transform(projection, v[cornerindex], temp);
10362 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10363 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10364 // calculate distance fade from the projection origin
10365 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10366 f = bound(0.0f, f, 1.0f);
10367 c[cornerindex][0] = r * f;
10368 c[cornerindex][1] = g * f;
10369 c[cornerindex][2] = b * f;
10370 c[cornerindex][3] = 1.0f;
10371 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10374 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);
10376 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10377 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);
10379 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)
10381 matrix4x4_t projection;
10382 decalsystem_t *decalsystem;
10385 const msurface_t *surface;
10386 const msurface_t *surfaces;
10387 const int *surfacelist;
10388 const texture_t *texture;
10390 int numsurfacelist;
10391 int surfacelistindex;
10394 float localorigin[3];
10395 float localnormal[3];
10396 float localmins[3];
10397 float localmaxs[3];
10400 float planes[6][4];
10403 int bih_triangles_count;
10404 int bih_triangles[256];
10405 int bih_surfaces[256];
10407 decalsystem = &ent->decalsystem;
10408 model = ent->model;
10409 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10411 R_DecalSystem_Reset(&ent->decalsystem);
10415 if (!model->brush.data_leafs && !cl_decals_models.integer)
10417 if (decalsystem->model)
10418 R_DecalSystem_Reset(decalsystem);
10422 if (decalsystem->model != model)
10423 R_DecalSystem_Reset(decalsystem);
10424 decalsystem->model = model;
10426 RSurf_ActiveModelEntity(ent, true, false, false);
10428 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10429 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10430 VectorNormalize(localnormal);
10431 localsize = worldsize*rsurface.inversematrixscale;
10432 localmins[0] = localorigin[0] - localsize;
10433 localmins[1] = localorigin[1] - localsize;
10434 localmins[2] = localorigin[2] - localsize;
10435 localmaxs[0] = localorigin[0] + localsize;
10436 localmaxs[1] = localorigin[1] + localsize;
10437 localmaxs[2] = localorigin[2] + localsize;
10439 //VectorCopy(localnormal, planes[4]);
10440 //VectorVectors(planes[4], planes[2], planes[0]);
10441 AnglesFromVectors(angles, localnormal, NULL, false);
10442 AngleVectors(angles, planes[0], planes[2], planes[4]);
10443 VectorNegate(planes[0], planes[1]);
10444 VectorNegate(planes[2], planes[3]);
10445 VectorNegate(planes[4], planes[5]);
10446 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10447 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10448 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10449 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10450 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10451 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10456 matrix4x4_t forwardprojection;
10457 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10458 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10463 float projectionvector[4][3];
10464 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10465 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10466 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10467 projectionvector[0][0] = planes[0][0] * ilocalsize;
10468 projectionvector[0][1] = planes[1][0] * ilocalsize;
10469 projectionvector[0][2] = planes[2][0] * ilocalsize;
10470 projectionvector[1][0] = planes[0][1] * ilocalsize;
10471 projectionvector[1][1] = planes[1][1] * ilocalsize;
10472 projectionvector[1][2] = planes[2][1] * ilocalsize;
10473 projectionvector[2][0] = planes[0][2] * ilocalsize;
10474 projectionvector[2][1] = planes[1][2] * ilocalsize;
10475 projectionvector[2][2] = planes[2][2] * ilocalsize;
10476 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10477 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10478 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10479 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10483 dynamic = model->surfmesh.isanimated;
10484 numsurfacelist = model->nummodelsurfaces;
10485 surfacelist = model->sortedmodelsurfaces;
10486 surfaces = model->data_surfaces;
10489 bih_triangles_count = -1;
10492 if(model->render_bih.numleafs)
10493 bih = &model->render_bih;
10494 else if(model->collision_bih.numleafs)
10495 bih = &model->collision_bih;
10498 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10499 if(bih_triangles_count == 0)
10501 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10503 if(bih_triangles_count > 0)
10505 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10507 surfaceindex = bih_surfaces[triangleindex];
10508 surface = surfaces + surfaceindex;
10509 texture = surface->texture;
10510 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10512 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10514 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10519 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10521 surfaceindex = surfacelist[surfacelistindex];
10522 surface = surfaces + surfaceindex;
10523 // check cull box first because it rejects more than any other check
10524 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10526 // skip transparent surfaces
10527 texture = surface->texture;
10528 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10530 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10532 numtriangles = surface->num_triangles;
10533 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10534 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10539 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10540 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)
10542 int renderentityindex;
10543 float worldmins[3];
10544 float worldmaxs[3];
10545 entity_render_t *ent;
10547 if (!cl_decals_newsystem.integer)
10550 worldmins[0] = worldorigin[0] - worldsize;
10551 worldmins[1] = worldorigin[1] - worldsize;
10552 worldmins[2] = worldorigin[2] - worldsize;
10553 worldmaxs[0] = worldorigin[0] + worldsize;
10554 worldmaxs[1] = worldorigin[1] + worldsize;
10555 worldmaxs[2] = worldorigin[2] + worldsize;
10557 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10559 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10561 ent = r_refdef.scene.entities[renderentityindex];
10562 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10565 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10569 typedef struct r_decalsystem_splatqueue_s
10571 vec3_t worldorigin;
10572 vec3_t worldnormal;
10578 r_decalsystem_splatqueue_t;
10580 int r_decalsystem_numqueued = 0;
10581 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10583 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)
10585 r_decalsystem_splatqueue_t *queue;
10587 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10590 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10591 VectorCopy(worldorigin, queue->worldorigin);
10592 VectorCopy(worldnormal, queue->worldnormal);
10593 Vector4Set(queue->color, r, g, b, a);
10594 Vector4Set(queue->tcrange, s1, t1, s2, t2);
10595 queue->worldsize = worldsize;
10596 queue->decalsequence = cl.decalsequence++;
10599 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10602 r_decalsystem_splatqueue_t *queue;
10604 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10605 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);
10606 r_decalsystem_numqueued = 0;
10609 extern cvar_t cl_decals_max;
10610 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10613 decalsystem_t *decalsystem = &ent->decalsystem;
10620 if (!decalsystem->numdecals)
10623 if (r_showsurfaces.integer)
10626 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10628 R_DecalSystem_Reset(decalsystem);
10632 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10633 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10635 if (decalsystem->lastupdatetime)
10636 frametime = (cl.time - decalsystem->lastupdatetime);
10639 decalsystem->lastupdatetime = cl.time;
10640 decal = decalsystem->decals;
10641 numdecals = decalsystem->numdecals;
10643 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10645 if (decal->color4f[0][3])
10647 decal->lived += frametime;
10648 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10650 memset(decal, 0, sizeof(*decal));
10651 if (decalsystem->freedecal > i)
10652 decalsystem->freedecal = i;
10656 decal = decalsystem->decals;
10657 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10660 // collapse the array by shuffling the tail decals into the gaps
10663 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10664 decalsystem->freedecal++;
10665 if (decalsystem->freedecal == numdecals)
10667 decal[decalsystem->freedecal] = decal[--numdecals];
10670 decalsystem->numdecals = numdecals;
10672 if (numdecals <= 0)
10674 // if there are no decals left, reset decalsystem
10675 R_DecalSystem_Reset(decalsystem);
10679 extern skinframe_t *decalskinframe;
10680 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10683 decalsystem_t *decalsystem = &ent->decalsystem;
10692 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10695 numdecals = decalsystem->numdecals;
10699 if (r_showsurfaces.integer)
10702 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10704 R_DecalSystem_Reset(decalsystem);
10708 // if the model is static it doesn't matter what value we give for
10709 // wantnormals and wanttangents, so this logic uses only rules applicable
10710 // to a model, knowing that they are meaningless otherwise
10711 if (ent == r_refdef.scene.worldentity)
10712 RSurf_ActiveWorldEntity();
10714 RSurf_ActiveModelEntity(ent, false, false, false);
10716 decalsystem->lastupdatetime = cl.time;
10717 decal = decalsystem->decals;
10719 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10721 // update vertex positions for animated models
10722 v3f = decalsystem->vertex3f;
10723 c4f = decalsystem->color4f;
10724 t2f = decalsystem->texcoord2f;
10725 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10727 if (!decal->color4f[0][3])
10730 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10733 // update color values for fading decals
10734 if (decal->lived >= cl_decals_time.value)
10735 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10739 c4f[ 0] = decal->color4f[0][0] * alpha;
10740 c4f[ 1] = decal->color4f[0][1] * alpha;
10741 c4f[ 2] = decal->color4f[0][2] * alpha;
10743 c4f[ 4] = decal->color4f[1][0] * alpha;
10744 c4f[ 5] = decal->color4f[1][1] * alpha;
10745 c4f[ 6] = decal->color4f[1][2] * alpha;
10747 c4f[ 8] = decal->color4f[2][0] * alpha;
10748 c4f[ 9] = decal->color4f[2][1] * alpha;
10749 c4f[10] = decal->color4f[2][2] * alpha;
10752 t2f[0] = decal->texcoord2f[0][0];
10753 t2f[1] = decal->texcoord2f[0][1];
10754 t2f[2] = decal->texcoord2f[1][0];
10755 t2f[3] = decal->texcoord2f[1][1];
10756 t2f[4] = decal->texcoord2f[2][0];
10757 t2f[5] = decal->texcoord2f[2][1];
10759 // update vertex positions for animated models
10760 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10762 e = rsurface.modelelement3i + 3*decal->triangleindex;
10763 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10764 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10765 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10769 VectorCopy(decal->vertex3f[0], v3f);
10770 VectorCopy(decal->vertex3f[1], v3f + 3);
10771 VectorCopy(decal->vertex3f[2], v3f + 6);
10774 if (r_refdef.fogenabled)
10776 alpha = RSurf_FogVertex(v3f);
10777 VectorScale(c4f, alpha, c4f);
10778 alpha = RSurf_FogVertex(v3f + 3);
10779 VectorScale(c4f + 4, alpha, c4f + 4);
10780 alpha = RSurf_FogVertex(v3f + 6);
10781 VectorScale(c4f + 8, alpha, c4f + 8);
10792 r_refdef.stats.drawndecals += numtris;
10794 // now render the decals all at once
10795 // (this assumes they all use one particle font texture!)
10796 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);
10797 // R_Mesh_ResetTextureState();
10798 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10799 GL_DepthMask(false);
10800 GL_DepthRange(0, 1);
10801 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10802 GL_DepthTest(true);
10803 GL_CullFace(GL_NONE);
10804 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10805 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10806 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10810 static void R_DrawModelDecals(void)
10814 // fade faster when there are too many decals
10815 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10816 for (i = 0;i < r_refdef.scene.numentities;i++)
10817 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10819 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10820 for (i = 0;i < r_refdef.scene.numentities;i++)
10821 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10822 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10824 R_DecalSystem_ApplySplatEntitiesQueue();
10826 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10827 for (i = 0;i < r_refdef.scene.numentities;i++)
10828 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10830 r_refdef.stats.totaldecals += numdecals;
10832 if (r_showsurfaces.integer)
10835 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10837 for (i = 0;i < r_refdef.scene.numentities;i++)
10839 if (!r_refdef.viewcache.entityvisible[i])
10841 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10842 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10846 extern cvar_t mod_collision_bih;
10847 void R_DrawDebugModel(void)
10849 entity_render_t *ent = rsurface.entity;
10850 int i, j, k, l, flagsmask;
10851 const msurface_t *surface;
10852 dp_model_t *model = ent->model;
10855 switch(vid.renderpath)
10857 case RENDERPATH_GL11:
10858 case RENDERPATH_GL13:
10859 case RENDERPATH_GL20:
10861 case RENDERPATH_D3D9:
10862 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10864 case RENDERPATH_D3D10:
10865 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10867 case RENDERPATH_D3D11:
10868 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10870 case RENDERPATH_SOFT:
10871 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10873 case RENDERPATH_GLES2:
10874 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10878 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
10880 // R_Mesh_ResetTextureState();
10881 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10882 GL_DepthRange(0, 1);
10883 GL_DepthTest(!r_showdisabledepthtest.integer);
10884 GL_DepthMask(false);
10885 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10887 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
10891 qboolean cullbox = ent == r_refdef.scene.worldentity;
10892 const q3mbrush_t *brush;
10893 const bih_t *bih = &model->collision_bih;
10894 const bih_leaf_t *bihleaf;
10895 float vertex3f[3][3];
10896 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
10898 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
10900 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
10902 switch (bihleaf->type)
10905 brush = model->brush.data_brushes + bihleaf->itemindex;
10906 if (brush->colbrushf && brush->colbrushf->numtriangles)
10908 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);
10909 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
10910 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
10913 case BIH_COLLISIONTRIANGLE:
10914 triangleindex = bihleaf->itemindex;
10915 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
10916 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
10917 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
10918 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);
10919 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10920 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10922 case BIH_RENDERTRIANGLE:
10923 triangleindex = bihleaf->itemindex;
10924 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
10925 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
10926 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
10927 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);
10928 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10929 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10935 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10937 if (r_showtris.integer || (r_shownormals.value != 0))
10939 if (r_showdisabledepthtest.integer)
10941 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10942 GL_DepthMask(false);
10946 GL_BlendFunc(GL_ONE, GL_ZERO);
10947 GL_DepthMask(true);
10949 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
10951 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
10953 rsurface.texture = R_GetCurrentTexture(surface->texture);
10954 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
10956 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
10957 if (r_showtris.value > 0)
10959 if (!rsurface.texture->currentlayers->depthmask)
10960 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
10961 else if (ent == r_refdef.scene.worldentity)
10962 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
10964 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
10965 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10966 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
10968 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
10971 if (r_shownormals.value < 0)
10973 qglBegin(GL_LINES);
10974 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10976 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10977 GL_Color(0, 0, r_refdef.view.colorscale, 1);
10978 qglVertex3f(v[0], v[1], v[2]);
10979 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
10980 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10981 qglVertex3f(v[0], v[1], v[2]);
10986 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
10988 qglBegin(GL_LINES);
10989 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10991 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10992 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
10993 qglVertex3f(v[0], v[1], v[2]);
10994 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
10995 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10996 qglVertex3f(v[0], v[1], v[2]);
11000 qglBegin(GL_LINES);
11001 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11003 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11004 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11005 qglVertex3f(v[0], v[1], v[2]);
11006 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11007 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11008 qglVertex3f(v[0], v[1], v[2]);
11012 qglBegin(GL_LINES);
11013 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11015 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11016 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11017 qglVertex3f(v[0], v[1], v[2]);
11018 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11019 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11020 qglVertex3f(v[0], v[1], v[2]);
11027 rsurface.texture = NULL;
11031 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11032 int r_maxsurfacelist = 0;
11033 const msurface_t **r_surfacelist = NULL;
11034 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11036 int i, j, endj, flagsmask;
11037 dp_model_t *model = r_refdef.scene.worldmodel;
11038 msurface_t *surfaces;
11039 unsigned char *update;
11040 int numsurfacelist = 0;
11044 if (r_maxsurfacelist < model->num_surfaces)
11046 r_maxsurfacelist = model->num_surfaces;
11048 Mem_Free((msurface_t**)r_surfacelist);
11049 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11052 RSurf_ActiveWorldEntity();
11054 surfaces = model->data_surfaces;
11055 update = model->brushq1.lightmapupdateflags;
11057 // update light styles on this submodel
11058 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11060 model_brush_lightstyleinfo_t *style;
11061 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11063 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11065 int *list = style->surfacelist;
11066 style->value = r_refdef.scene.lightstylevalue[style->style];
11067 for (j = 0;j < style->numsurfaces;j++)
11068 update[list[j]] = true;
11073 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11077 R_DrawDebugModel();
11078 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11082 rsurface.lightmaptexture = NULL;
11083 rsurface.deluxemaptexture = NULL;
11084 rsurface.uselightmaptexture = false;
11085 rsurface.texture = NULL;
11086 rsurface.rtlight = NULL;
11087 numsurfacelist = 0;
11088 // add visible surfaces to draw list
11089 for (i = 0;i < model->nummodelsurfaces;i++)
11091 j = model->sortedmodelsurfaces[i];
11092 if (r_refdef.viewcache.world_surfacevisible[j])
11093 r_surfacelist[numsurfacelist++] = surfaces + j;
11095 // update lightmaps if needed
11096 if (model->brushq1.firstrender)
11098 model->brushq1.firstrender = false;
11099 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11101 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11105 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11106 if (r_refdef.viewcache.world_surfacevisible[j])
11108 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11110 // don't do anything if there were no surfaces
11111 if (!numsurfacelist)
11113 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11116 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11118 // add to stats if desired
11119 if (r_speeds.integer && !skysurfaces && !depthonly)
11121 r_refdef.stats.world_surfaces += numsurfacelist;
11122 for (j = 0;j < numsurfacelist;j++)
11123 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11126 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11129 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11131 int i, j, endj, flagsmask;
11132 dp_model_t *model = ent->model;
11133 msurface_t *surfaces;
11134 unsigned char *update;
11135 int numsurfacelist = 0;
11139 if (r_maxsurfacelist < model->num_surfaces)
11141 r_maxsurfacelist = model->num_surfaces;
11143 Mem_Free((msurface_t **)r_surfacelist);
11144 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11147 // if the model is static it doesn't matter what value we give for
11148 // wantnormals and wanttangents, so this logic uses only rules applicable
11149 // to a model, knowing that they are meaningless otherwise
11150 if (ent == r_refdef.scene.worldentity)
11151 RSurf_ActiveWorldEntity();
11152 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11153 RSurf_ActiveModelEntity(ent, false, false, false);
11155 RSurf_ActiveModelEntity(ent, true, true, true);
11156 else if (depthonly)
11158 switch (vid.renderpath)
11160 case RENDERPATH_GL20:
11161 case RENDERPATH_D3D9:
11162 case RENDERPATH_D3D10:
11163 case RENDERPATH_D3D11:
11164 case RENDERPATH_SOFT:
11165 case RENDERPATH_GLES2:
11166 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11168 case RENDERPATH_GL13:
11169 case RENDERPATH_GL11:
11170 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11176 switch (vid.renderpath)
11178 case RENDERPATH_GL20:
11179 case RENDERPATH_D3D9:
11180 case RENDERPATH_D3D10:
11181 case RENDERPATH_D3D11:
11182 case RENDERPATH_SOFT:
11183 case RENDERPATH_GLES2:
11184 RSurf_ActiveModelEntity(ent, true, true, false);
11186 case RENDERPATH_GL13:
11187 case RENDERPATH_GL11:
11188 RSurf_ActiveModelEntity(ent, true, false, false);
11193 surfaces = model->data_surfaces;
11194 update = model->brushq1.lightmapupdateflags;
11196 // update light styles
11197 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11199 model_brush_lightstyleinfo_t *style;
11200 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11202 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11204 int *list = style->surfacelist;
11205 style->value = r_refdef.scene.lightstylevalue[style->style];
11206 for (j = 0;j < style->numsurfaces;j++)
11207 update[list[j]] = true;
11212 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11216 R_DrawDebugModel();
11217 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11221 rsurface.lightmaptexture = NULL;
11222 rsurface.deluxemaptexture = NULL;
11223 rsurface.uselightmaptexture = false;
11224 rsurface.texture = NULL;
11225 rsurface.rtlight = NULL;
11226 numsurfacelist = 0;
11227 // add visible surfaces to draw list
11228 for (i = 0;i < model->nummodelsurfaces;i++)
11229 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11230 // don't do anything if there were no surfaces
11231 if (!numsurfacelist)
11233 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11236 // update lightmaps if needed
11240 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11245 R_BuildLightMap(ent, surfaces + j);
11250 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11252 R_BuildLightMap(ent, surfaces + j);
11253 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11255 // add to stats if desired
11256 if (r_speeds.integer && !skysurfaces && !depthonly)
11258 r_refdef.stats.entities_surfaces += numsurfacelist;
11259 for (j = 0;j < numsurfacelist;j++)
11260 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11263 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11266 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11268 static texture_t texture;
11269 static msurface_t surface;
11270 const msurface_t *surfacelist = &surface;
11272 // fake enough texture and surface state to render this geometry
11274 texture.update_lastrenderframe = -1; // regenerate this texture
11275 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11276 texture.currentskinframe = skinframe;
11277 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11278 texture.offsetmapping = OFFSETMAPPING_OFF;
11279 texture.offsetscale = 1;
11280 texture.specularscalemod = 1;
11281 texture.specularpowermod = 1;
11283 surface.texture = &texture;
11284 surface.num_triangles = numtriangles;
11285 surface.num_firsttriangle = firsttriangle;
11286 surface.num_vertices = numvertices;
11287 surface.num_firstvertex = firstvertex;
11290 rsurface.texture = R_GetCurrentTexture(surface.texture);
11291 rsurface.lightmaptexture = NULL;
11292 rsurface.deluxemaptexture = NULL;
11293 rsurface.uselightmaptexture = false;
11294 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11297 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)
11299 static msurface_t surface;
11300 const msurface_t *surfacelist = &surface;
11302 // fake enough texture and surface state to render this geometry
11303 surface.texture = texture;
11304 surface.num_triangles = numtriangles;
11305 surface.num_firsttriangle = firsttriangle;
11306 surface.num_vertices = numvertices;
11307 surface.num_firstvertex = firstvertex;
11310 rsurface.texture = R_GetCurrentTexture(surface.texture);
11311 rsurface.lightmaptexture = NULL;
11312 rsurface.deluxemaptexture = NULL;
11313 rsurface.uselightmaptexture = false;
11314 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);