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_sRGB_2d = {0, "r_texture_sRGB_2d", "0", "load textures as sRGB"};
135 cvar_t r_texture_sRGB_skin_diffuse = {0, "r_texture_sRGB_skin_diffuse", "0", "load textures as sRGB"};
136 cvar_t r_texture_sRGB_skin_gloss = {0, "r_texture_sRGB_skin_gloss", "0", "load textures as sRGB"};
137 cvar_t r_texture_sRGB_skin_glow = {0, "r_texture_sRGB_skin_glow", "0", "load textures as sRGB"};
138 cvar_t r_texture_sRGB_skin_reflect = {0, "r_texture_sRGB_skin_reflect", "0", "load textures as sRGB"};
139 cvar_t r_texture_sRGB_cubemap = {0, "r_texture_sRGB_cubemap", "0", "load textures as sRGB"};
140 cvar_t r_texture_sRGB_skybox = {0, "r_texture_sRGB_skybox", "0", "load textures as sRGB"};
142 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
143 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
144 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
146 cvar_t r_viewfbo = {CVAR_SAVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"};
147 cvar_t r_viewscale = {CVAR_SAVE, "r_viewscale", "1", "scaling factor for resolution of the fbo rendering method, must be > 0, can be above 1 for a costly antialiasing behavior, typical values are 0.5 for 1/4th as many pixels rendered, or 1 for normal rendering"};
148 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
149 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
150 cvar_t r_viewscale_fpsscaling_multiply = {CVAR_SAVE, "r_viewscale_fpsscaling_multiply", "5", "adjust quality up or down by the frametime difference from 1.0/target, multiplied by this factor"};
151 cvar_t r_viewscale_fpsscaling_stepsize = {CVAR_SAVE, "r_viewscale_fpsscaling_stepsize", "0.01", "smallest adjustment to hit the target framerate (this value prevents minute oscillations)"};
152 cvar_t r_viewscale_fpsscaling_stepmax = {CVAR_SAVE, "r_viewscale_fpsscaling_stepmax", "1.00", "largest adjustment to hit the target framerate (this value prevents wild overshooting of the estimate)"};
153 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
155 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)"};
156 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
157 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)"};
158 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
159 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)"};
160 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
161 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
162 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)"};
163 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)"};
164 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)"};
165 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)"};
166 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)"};
167 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)"};
168 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)"};
169 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)"};
171 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)"};
172 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
173 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"};
174 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
175 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
176 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
178 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
179 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
180 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
181 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
183 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
184 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
185 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
186 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
187 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
188 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
189 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
191 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
192 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
193 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
194 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)"};
195 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
196 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
197 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
198 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
199 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
200 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
202 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"};
204 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"};
206 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
208 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
209 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"};
210 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
211 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
212 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
213 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
214 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)"};
215 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
216 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
218 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
219 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"};
221 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."};
223 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)"};
225 extern cvar_t v_glslgamma;
227 extern qboolean v_flipped_state;
229 static struct r_bloomstate_s
234 int bloomwidth, bloomheight;
236 textype_t texturetype;
237 int viewfbo; // used to check if r_viewfbo cvar has changed
239 int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
240 rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
241 rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
243 int screentexturewidth, screentextureheight;
244 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
246 int bloomtexturewidth, bloomtextureheight;
247 rtexture_t *texture_bloom;
249 // arrays for rendering the screen passes
250 float screentexcoord2f[8];
251 float bloomtexcoord2f[8];
252 float offsettexcoord2f[8];
254 r_viewport_t viewport;
258 r_waterstate_t r_waterstate;
260 /// shadow volume bsp struct with automatically growing nodes buffer
263 rtexture_t *r_texture_blanknormalmap;
264 rtexture_t *r_texture_white;
265 rtexture_t *r_texture_grey128;
266 rtexture_t *r_texture_black;
267 rtexture_t *r_texture_notexture;
268 rtexture_t *r_texture_whitecube;
269 rtexture_t *r_texture_normalizationcube;
270 rtexture_t *r_texture_fogattenuation;
271 rtexture_t *r_texture_fogheighttexture;
272 rtexture_t *r_texture_gammaramps;
273 unsigned int r_texture_gammaramps_serial;
274 //rtexture_t *r_texture_fogintensity;
275 rtexture_t *r_texture_reflectcube;
277 // TODO: hash lookups?
278 typedef struct cubemapinfo_s
285 int r_texture_numcubemaps;
286 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
288 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
289 unsigned int r_numqueries;
290 unsigned int r_maxqueries;
292 typedef struct r_qwskincache_s
294 char name[MAX_QPATH];
295 skinframe_t *skinframe;
299 static r_qwskincache_t *r_qwskincache;
300 static int r_qwskincache_size;
302 /// vertex coordinates for a quad that covers the screen exactly
303 extern const float r_screenvertex3f[12];
304 extern const float r_d3dscreenvertex3f[12];
305 const float r_screenvertex3f[12] =
312 const float r_d3dscreenvertex3f[12] =
320 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
323 for (i = 0;i < verts;i++)
334 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
337 for (i = 0;i < verts;i++)
347 // FIXME: move this to client?
350 if (gamemode == GAME_NEHAHRA)
352 Cvar_Set("gl_fogenable", "0");
353 Cvar_Set("gl_fogdensity", "0.2");
354 Cvar_Set("gl_fogred", "0.3");
355 Cvar_Set("gl_foggreen", "0.3");
356 Cvar_Set("gl_fogblue", "0.3");
358 r_refdef.fog_density = 0;
359 r_refdef.fog_red = 0;
360 r_refdef.fog_green = 0;
361 r_refdef.fog_blue = 0;
362 r_refdef.fog_alpha = 1;
363 r_refdef.fog_start = 0;
364 r_refdef.fog_end = 16384;
365 r_refdef.fog_height = 1<<30;
366 r_refdef.fog_fadedepth = 128;
367 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
370 static void R_BuildBlankTextures(void)
372 unsigned char data[4];
373 data[2] = 128; // normal X
374 data[1] = 128; // normal Y
375 data[0] = 255; // normal Z
376 data[3] = 128; // height
377 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
382 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
387 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
392 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
395 static void R_BuildNoTexture(void)
398 unsigned char pix[16][16][4];
399 // this makes a light grey/dark grey checkerboard texture
400 for (y = 0;y < 16;y++)
402 for (x = 0;x < 16;x++)
404 if ((y < 8) ^ (x < 8))
420 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
423 static void R_BuildWhiteCube(void)
425 unsigned char data[6*1*1*4];
426 memset(data, 255, sizeof(data));
427 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
430 static void R_BuildNormalizationCube(void)
434 vec_t s, t, intensity;
437 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
438 for (side = 0;side < 6;side++)
440 for (y = 0;y < NORMSIZE;y++)
442 for (x = 0;x < NORMSIZE;x++)
444 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
445 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
480 intensity = 127.0f / sqrt(DotProduct(v, v));
481 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
482 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
483 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
484 data[((side*64+y)*64+x)*4+3] = 255;
488 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
492 static void R_BuildFogTexture(void)
496 unsigned char data1[FOGWIDTH][4];
497 //unsigned char data2[FOGWIDTH][4];
500 r_refdef.fogmasktable_start = r_refdef.fog_start;
501 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
502 r_refdef.fogmasktable_range = r_refdef.fogrange;
503 r_refdef.fogmasktable_density = r_refdef.fog_density;
505 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
506 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
508 d = (x * r - r_refdef.fogmasktable_start);
509 if(developer_extra.integer)
510 Con_DPrintf("%f ", d);
512 if (r_fog_exp2.integer)
513 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
515 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
516 if(developer_extra.integer)
517 Con_DPrintf(" : %f ", alpha);
518 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
519 if(developer_extra.integer)
520 Con_DPrintf(" = %f\n", alpha);
521 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
524 for (x = 0;x < FOGWIDTH;x++)
526 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
531 //data2[x][0] = 255 - b;
532 //data2[x][1] = 255 - b;
533 //data2[x][2] = 255 - b;
536 if (r_texture_fogattenuation)
538 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
539 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
543 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
544 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
548 static void R_BuildFogHeightTexture(void)
550 unsigned char *inpixels;
558 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
559 if (r_refdef.fogheighttexturename[0])
560 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
563 r_refdef.fog_height_tablesize = 0;
564 if (r_texture_fogheighttexture)
565 R_FreeTexture(r_texture_fogheighttexture);
566 r_texture_fogheighttexture = NULL;
567 if (r_refdef.fog_height_table2d)
568 Mem_Free(r_refdef.fog_height_table2d);
569 r_refdef.fog_height_table2d = NULL;
570 if (r_refdef.fog_height_table1d)
571 Mem_Free(r_refdef.fog_height_table1d);
572 r_refdef.fog_height_table1d = NULL;
576 r_refdef.fog_height_tablesize = size;
577 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
578 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
579 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
581 // LordHavoc: now the magic - what is that table2d for? it is a cooked
582 // average fog color table accounting for every fog layer between a point
583 // and the camera. (Note: attenuation is handled separately!)
584 for (y = 0;y < size;y++)
586 for (x = 0;x < size;x++)
592 for (j = x;j <= y;j++)
594 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
600 for (j = x;j >= y;j--)
602 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
607 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
608 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
609 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
610 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
613 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
616 //=======================================================================================================================================================
618 static const char *builtinshaderstring =
619 #include "shader_glsl.h"
622 const char *builtinhlslshaderstring =
623 #include "shader_hlsl.h"
626 char *glslshaderstring = NULL;
627 char *hlslshaderstring = NULL;
629 //=======================================================================================================================================================
631 typedef struct shaderpermutationinfo_s
636 shaderpermutationinfo_t;
638 typedef struct shadermodeinfo_s
640 const char *vertexfilename;
641 const char *geometryfilename;
642 const char *fragmentfilename;
648 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
649 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
651 {"#define USEDIFFUSE\n", " diffuse"},
652 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
653 {"#define USEVIEWTINT\n", " viewtint"},
654 {"#define USECOLORMAPPING\n", " colormapping"},
655 {"#define USESATURATION\n", " saturation"},
656 {"#define USEFOGINSIDE\n", " foginside"},
657 {"#define USEFOGOUTSIDE\n", " fogoutside"},
658 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
659 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
660 {"#define USEGAMMARAMPS\n", " gammaramps"},
661 {"#define USECUBEFILTER\n", " cubefilter"},
662 {"#define USEGLOW\n", " glow"},
663 {"#define USEBLOOM\n", " bloom"},
664 {"#define USESPECULAR\n", " specular"},
665 {"#define USEPOSTPROCESSING\n", " postprocessing"},
666 {"#define USEREFLECTION\n", " reflection"},
667 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
668 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
669 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
670 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
671 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
672 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
673 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
674 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
675 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
676 {"#define USEALPHAKILL\n", " alphakill"},
677 {"#define USEREFLECTCUBE\n", " reflectcube"},
678 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
679 {"#define USEBOUNCEGRID\n", " bouncegrid"},
680 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
683 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
684 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
686 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
687 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
688 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
689 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
690 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
691 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
692 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
693 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
694 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
695 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
696 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
697 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
698 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
699 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
700 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
701 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
704 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
706 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
707 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
708 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
709 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
710 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
711 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
712 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
713 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
714 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
715 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
716 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
717 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
718 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
719 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
720 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
721 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
724 struct r_glsl_permutation_s;
725 typedef struct r_glsl_permutation_s
728 struct r_glsl_permutation_s *hashnext;
730 unsigned int permutation;
732 /// indicates if we have tried compiling this permutation already
734 /// 0 if compilation failed
736 // texture units assigned to each detected uniform
737 int tex_Texture_First;
738 int tex_Texture_Second;
739 int tex_Texture_GammaRamps;
740 int tex_Texture_Normal;
741 int tex_Texture_Color;
742 int tex_Texture_Gloss;
743 int tex_Texture_Glow;
744 int tex_Texture_SecondaryNormal;
745 int tex_Texture_SecondaryColor;
746 int tex_Texture_SecondaryGloss;
747 int tex_Texture_SecondaryGlow;
748 int tex_Texture_Pants;
749 int tex_Texture_Shirt;
750 int tex_Texture_FogHeightTexture;
751 int tex_Texture_FogMask;
752 int tex_Texture_Lightmap;
753 int tex_Texture_Deluxemap;
754 int tex_Texture_Attenuation;
755 int tex_Texture_Cube;
756 int tex_Texture_Refraction;
757 int tex_Texture_Reflection;
758 int tex_Texture_ShadowMap2D;
759 int tex_Texture_CubeProjection;
760 int tex_Texture_ScreenDepth;
761 int tex_Texture_ScreenNormalMap;
762 int tex_Texture_ScreenDiffuse;
763 int tex_Texture_ScreenSpecular;
764 int tex_Texture_ReflectMask;
765 int tex_Texture_ReflectCube;
766 int tex_Texture_BounceGrid;
767 /// locations of detected uniforms in program object, or -1 if not found
768 int loc_Texture_First;
769 int loc_Texture_Second;
770 int loc_Texture_GammaRamps;
771 int loc_Texture_Normal;
772 int loc_Texture_Color;
773 int loc_Texture_Gloss;
774 int loc_Texture_Glow;
775 int loc_Texture_SecondaryNormal;
776 int loc_Texture_SecondaryColor;
777 int loc_Texture_SecondaryGloss;
778 int loc_Texture_SecondaryGlow;
779 int loc_Texture_Pants;
780 int loc_Texture_Shirt;
781 int loc_Texture_FogHeightTexture;
782 int loc_Texture_FogMask;
783 int loc_Texture_Lightmap;
784 int loc_Texture_Deluxemap;
785 int loc_Texture_Attenuation;
786 int loc_Texture_Cube;
787 int loc_Texture_Refraction;
788 int loc_Texture_Reflection;
789 int loc_Texture_ShadowMap2D;
790 int loc_Texture_CubeProjection;
791 int loc_Texture_ScreenDepth;
792 int loc_Texture_ScreenNormalMap;
793 int loc_Texture_ScreenDiffuse;
794 int loc_Texture_ScreenSpecular;
795 int loc_Texture_ReflectMask;
796 int loc_Texture_ReflectCube;
797 int loc_Texture_BounceGrid;
799 int loc_BloomBlur_Parameters;
801 int loc_Color_Ambient;
802 int loc_Color_Diffuse;
803 int loc_Color_Specular;
807 int loc_DeferredColor_Ambient;
808 int loc_DeferredColor_Diffuse;
809 int loc_DeferredColor_Specular;
810 int loc_DeferredMod_Diffuse;
811 int loc_DeferredMod_Specular;
812 int loc_DistortScaleRefractReflect;
815 int loc_FogHeightFade;
817 int loc_FogPlaneViewDist;
818 int loc_FogRangeRecip;
821 int loc_LightPosition;
822 int loc_OffsetMapping_ScaleSteps;
824 int loc_ReflectColor;
825 int loc_ReflectFactor;
826 int loc_ReflectOffset;
827 int loc_RefractColor;
829 int loc_ScreenCenterRefractReflect;
830 int loc_ScreenScaleRefractReflect;
831 int loc_ScreenToDepth;
832 int loc_ShadowMap_Parameters;
833 int loc_ShadowMap_TextureScale;
834 int loc_SpecularPower;
839 int loc_ViewTintColor;
841 int loc_ModelToLight;
843 int loc_BackgroundTexMatrix;
844 int loc_ModelViewProjectionMatrix;
845 int loc_ModelViewMatrix;
846 int loc_PixelToScreenTexCoord;
847 int loc_ModelToReflectCube;
848 int loc_ShadowMapMatrix;
849 int loc_BloomColorSubtract;
850 int loc_NormalmapScrollBlend;
851 int loc_BounceGridMatrix;
852 int loc_BounceGridIntensity;
854 r_glsl_permutation_t;
856 #define SHADERPERMUTATION_HASHSIZE 256
859 // non-degradable "lightweight" shader parameters to keep the permutations simpler
860 // these can NOT degrade! only use for simple stuff
863 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
864 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
865 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
866 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
867 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
868 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
869 SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
871 #define SHADERSTATICPARMS_COUNT 7
873 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
874 static int shaderstaticparms_count = 0;
876 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
877 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
878 qboolean R_CompileShader_CheckStaticParms(void)
880 static int r_compileshader_staticparms_save[1];
881 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
882 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
885 if (r_glsl_saturation_redcompensate.integer)
886 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
887 if (r_glsl_vertextextureblend_usebothalphas.integer)
888 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
889 if (r_shadow_glossexact.integer)
890 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
891 if (r_glsl_postprocess.integer)
893 if (r_glsl_postprocess_uservec1_enable.integer)
894 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
895 if (r_glsl_postprocess_uservec2_enable.integer)
896 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
897 if (r_glsl_postprocess_uservec3_enable.integer)
898 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
899 if (r_glsl_postprocess_uservec4_enable.integer)
900 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
902 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
905 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
906 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
907 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
909 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
910 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
912 shaderstaticparms_count = 0;
915 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
916 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
917 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
918 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
919 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
920 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
921 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
924 /// information about each possible shader permutation
925 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
926 /// currently selected permutation
927 r_glsl_permutation_t *r_glsl_permutation;
928 /// storage for permutations linked in the hash table
929 memexpandablearray_t r_glsl_permutationarray;
931 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
933 //unsigned int hashdepth = 0;
934 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
935 r_glsl_permutation_t *p;
936 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
938 if (p->mode == mode && p->permutation == permutation)
940 //if (hashdepth > 10)
941 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
946 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
948 p->permutation = permutation;
949 p->hashnext = r_glsl_permutationhash[mode][hashindex];
950 r_glsl_permutationhash[mode][hashindex] = p;
951 //if (hashdepth > 10)
952 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
956 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
959 if (!filename || !filename[0])
961 if (!strcmp(filename, "glsl/default.glsl"))
963 if (!glslshaderstring)
965 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
966 if (glslshaderstring)
967 Con_DPrintf("Loading shaders from file %s...\n", filename);
969 glslshaderstring = (char *)builtinshaderstring;
971 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
972 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
975 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
978 if (printfromdisknotice)
979 Con_DPrintf("from disk %s... ", filename);
985 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
989 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
990 char *vertexstring, *geometrystring, *fragmentstring;
991 char permutationname[256];
992 int vertstrings_count = 0;
993 int geomstrings_count = 0;
994 int fragstrings_count = 0;
995 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
996 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
997 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1004 permutationname[0] = 0;
1005 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1006 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1007 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1009 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1011 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1012 if(vid.support.gl20shaders130)
1014 vertstrings_list[vertstrings_count++] = "#version 130\n";
1015 geomstrings_list[geomstrings_count++] = "#version 130\n";
1016 fragstrings_list[fragstrings_count++] = "#version 130\n";
1017 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1018 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1019 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1022 // the first pretext is which type of shader to compile as
1023 // (later these will all be bound together as a program object)
1024 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1025 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1026 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1028 // the second pretext is the mode (for example a light source)
1029 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1030 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1031 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1032 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1034 // now add all the permutation pretexts
1035 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1037 if (permutation & (1<<i))
1039 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1040 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1041 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1042 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1046 // keep line numbers correct
1047 vertstrings_list[vertstrings_count++] = "\n";
1048 geomstrings_list[geomstrings_count++] = "\n";
1049 fragstrings_list[fragstrings_count++] = "\n";
1054 R_CompileShader_AddStaticParms(mode, permutation);
1055 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1056 vertstrings_count += shaderstaticparms_count;
1057 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1058 geomstrings_count += shaderstaticparms_count;
1059 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1060 fragstrings_count += shaderstaticparms_count;
1062 // now append the shader text itself
1063 vertstrings_list[vertstrings_count++] = vertexstring;
1064 geomstrings_list[geomstrings_count++] = geometrystring;
1065 fragstrings_list[fragstrings_count++] = fragmentstring;
1067 // if any sources were NULL, clear the respective list
1069 vertstrings_count = 0;
1070 if (!geometrystring)
1071 geomstrings_count = 0;
1072 if (!fragmentstring)
1073 fragstrings_count = 0;
1075 // compile the shader program
1076 if (vertstrings_count + geomstrings_count + fragstrings_count)
1077 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1081 qglUseProgram(p->program);CHECKGLERROR
1082 // look up all the uniform variable names we care about, so we don't
1083 // have to look them up every time we set them
1085 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1086 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1087 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1088 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1089 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1090 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1091 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1092 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1093 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1094 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1095 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1096 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1097 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1098 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1099 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1100 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1101 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1102 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1103 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1104 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1105 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1106 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1107 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1108 p->loc_Texture_ScreenDepth = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1109 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1110 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1111 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1112 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1113 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1114 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1115 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1116 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1117 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1118 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1119 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1120 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1121 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1122 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1123 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1124 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1125 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1126 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1127 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1128 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1129 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1130 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1131 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1132 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1133 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1134 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1135 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1136 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1137 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1138 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1139 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1140 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1141 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1142 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1143 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1144 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1145 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1146 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1147 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1148 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1149 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1150 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1151 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1152 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1153 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1154 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1155 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1156 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1157 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1158 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1159 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1160 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1161 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1162 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1163 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1164 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1165 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1166 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1167 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1168 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1169 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1170 // initialize the samplers to refer to the texture units we use
1171 p->tex_Texture_First = -1;
1172 p->tex_Texture_Second = -1;
1173 p->tex_Texture_GammaRamps = -1;
1174 p->tex_Texture_Normal = -1;
1175 p->tex_Texture_Color = -1;
1176 p->tex_Texture_Gloss = -1;
1177 p->tex_Texture_Glow = -1;
1178 p->tex_Texture_SecondaryNormal = -1;
1179 p->tex_Texture_SecondaryColor = -1;
1180 p->tex_Texture_SecondaryGloss = -1;
1181 p->tex_Texture_SecondaryGlow = -1;
1182 p->tex_Texture_Pants = -1;
1183 p->tex_Texture_Shirt = -1;
1184 p->tex_Texture_FogHeightTexture = -1;
1185 p->tex_Texture_FogMask = -1;
1186 p->tex_Texture_Lightmap = -1;
1187 p->tex_Texture_Deluxemap = -1;
1188 p->tex_Texture_Attenuation = -1;
1189 p->tex_Texture_Cube = -1;
1190 p->tex_Texture_Refraction = -1;
1191 p->tex_Texture_Reflection = -1;
1192 p->tex_Texture_ShadowMap2D = -1;
1193 p->tex_Texture_CubeProjection = -1;
1194 p->tex_Texture_ScreenDepth = -1;
1195 p->tex_Texture_ScreenNormalMap = -1;
1196 p->tex_Texture_ScreenDiffuse = -1;
1197 p->tex_Texture_ScreenSpecular = -1;
1198 p->tex_Texture_ReflectMask = -1;
1199 p->tex_Texture_ReflectCube = -1;
1200 p->tex_Texture_BounceGrid = -1;
1202 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1203 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1204 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1205 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1206 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1207 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1208 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1209 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1210 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1211 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1212 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1213 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1214 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1215 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1216 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1217 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1218 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1219 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1220 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1221 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1222 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1223 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1224 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1225 if (p->loc_Texture_ScreenDepth >= 0) {p->tex_Texture_ScreenDepth = sampler;qglUniform1i(p->loc_Texture_ScreenDepth , sampler);sampler++;}
1226 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1227 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1228 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1229 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1230 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1231 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1233 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1236 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1240 Mem_Free(vertexstring);
1242 Mem_Free(geometrystring);
1244 Mem_Free(fragmentstring);
1247 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1249 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1250 if (r_glsl_permutation != perm)
1252 r_glsl_permutation = perm;
1253 if (!r_glsl_permutation->program)
1255 if (!r_glsl_permutation->compiled)
1256 R_GLSL_CompilePermutation(perm, mode, permutation);
1257 if (!r_glsl_permutation->program)
1259 // remove features until we find a valid permutation
1261 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1263 // reduce i more quickly whenever it would not remove any bits
1264 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1265 if (!(permutation & j))
1268 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1269 if (!r_glsl_permutation->compiled)
1270 R_GLSL_CompilePermutation(perm, mode, permutation);
1271 if (r_glsl_permutation->program)
1274 if (i >= SHADERPERMUTATION_COUNT)
1276 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1277 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1278 qglUseProgram(0);CHECKGLERROR
1279 return; // no bit left to clear, entire mode is broken
1284 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1286 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1287 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1288 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1295 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1296 extern D3DCAPS9 vid_d3d9caps;
1299 struct r_hlsl_permutation_s;
1300 typedef struct r_hlsl_permutation_s
1302 /// hash lookup data
1303 struct r_hlsl_permutation_s *hashnext;
1305 unsigned int permutation;
1307 /// indicates if we have tried compiling this permutation already
1309 /// NULL if compilation failed
1310 IDirect3DVertexShader9 *vertexshader;
1311 IDirect3DPixelShader9 *pixelshader;
1313 r_hlsl_permutation_t;
1315 typedef enum D3DVSREGISTER_e
1317 D3DVSREGISTER_TexMatrix = 0, // float4x4
1318 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1319 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1320 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1321 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1322 D3DVSREGISTER_ModelToLight = 20, // float4x4
1323 D3DVSREGISTER_EyePosition = 24,
1324 D3DVSREGISTER_FogPlane = 25,
1325 D3DVSREGISTER_LightDir = 26,
1326 D3DVSREGISTER_LightPosition = 27,
1330 typedef enum D3DPSREGISTER_e
1332 D3DPSREGISTER_Alpha = 0,
1333 D3DPSREGISTER_BloomBlur_Parameters = 1,
1334 D3DPSREGISTER_ClientTime = 2,
1335 D3DPSREGISTER_Color_Ambient = 3,
1336 D3DPSREGISTER_Color_Diffuse = 4,
1337 D3DPSREGISTER_Color_Specular = 5,
1338 D3DPSREGISTER_Color_Glow = 6,
1339 D3DPSREGISTER_Color_Pants = 7,
1340 D3DPSREGISTER_Color_Shirt = 8,
1341 D3DPSREGISTER_DeferredColor_Ambient = 9,
1342 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1343 D3DPSREGISTER_DeferredColor_Specular = 11,
1344 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1345 D3DPSREGISTER_DeferredMod_Specular = 13,
1346 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1347 D3DPSREGISTER_EyePosition = 15, // unused
1348 D3DPSREGISTER_FogColor = 16,
1349 D3DPSREGISTER_FogHeightFade = 17,
1350 D3DPSREGISTER_FogPlane = 18,
1351 D3DPSREGISTER_FogPlaneViewDist = 19,
1352 D3DPSREGISTER_FogRangeRecip = 20,
1353 D3DPSREGISTER_LightColor = 21,
1354 D3DPSREGISTER_LightDir = 22, // unused
1355 D3DPSREGISTER_LightPosition = 23,
1356 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1357 D3DPSREGISTER_PixelSize = 25,
1358 D3DPSREGISTER_ReflectColor = 26,
1359 D3DPSREGISTER_ReflectFactor = 27,
1360 D3DPSREGISTER_ReflectOffset = 28,
1361 D3DPSREGISTER_RefractColor = 29,
1362 D3DPSREGISTER_Saturation = 30,
1363 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1364 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1365 D3DPSREGISTER_ScreenToDepth = 33,
1366 D3DPSREGISTER_ShadowMap_Parameters = 34,
1367 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1368 D3DPSREGISTER_SpecularPower = 36,
1369 D3DPSREGISTER_UserVec1 = 37,
1370 D3DPSREGISTER_UserVec2 = 38,
1371 D3DPSREGISTER_UserVec3 = 39,
1372 D3DPSREGISTER_UserVec4 = 40,
1373 D3DPSREGISTER_ViewTintColor = 41,
1374 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1375 D3DPSREGISTER_BloomColorSubtract = 43,
1376 D3DPSREGISTER_ViewToLight = 44, // float4x4
1377 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1378 D3DPSREGISTER_NormalmapScrollBlend = 52,
1383 /// information about each possible shader permutation
1384 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1385 /// currently selected permutation
1386 r_hlsl_permutation_t *r_hlsl_permutation;
1387 /// storage for permutations linked in the hash table
1388 memexpandablearray_t r_hlsl_permutationarray;
1390 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1392 //unsigned int hashdepth = 0;
1393 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1394 r_hlsl_permutation_t *p;
1395 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1397 if (p->mode == mode && p->permutation == permutation)
1399 //if (hashdepth > 10)
1400 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1405 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1407 p->permutation = permutation;
1408 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1409 r_hlsl_permutationhash[mode][hashindex] = p;
1410 //if (hashdepth > 10)
1411 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1415 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1418 if (!filename || !filename[0])
1420 if (!strcmp(filename, "hlsl/default.hlsl"))
1422 if (!hlslshaderstring)
1424 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1425 if (hlslshaderstring)
1426 Con_DPrintf("Loading shaders from file %s...\n", filename);
1428 hlslshaderstring = (char *)builtinhlslshaderstring;
1430 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1431 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1432 return shaderstring;
1434 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1437 if (printfromdisknotice)
1438 Con_DPrintf("from disk %s... ", filename);
1439 return shaderstring;
1441 return shaderstring;
1445 //#include <d3dx9shader.h>
1446 //#include <d3dx9mesh.h>
1448 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1450 DWORD *vsbin = NULL;
1451 DWORD *psbin = NULL;
1452 fs_offset_t vsbinsize;
1453 fs_offset_t psbinsize;
1454 // IDirect3DVertexShader9 *vs = NULL;
1455 // IDirect3DPixelShader9 *ps = NULL;
1456 ID3DXBuffer *vslog = NULL;
1457 ID3DXBuffer *vsbuffer = NULL;
1458 ID3DXConstantTable *vsconstanttable = NULL;
1459 ID3DXBuffer *pslog = NULL;
1460 ID3DXBuffer *psbuffer = NULL;
1461 ID3DXConstantTable *psconstanttable = NULL;
1464 char temp[MAX_INPUTLINE];
1465 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1466 qboolean debugshader = gl_paranoid.integer != 0;
1467 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1468 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1471 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1472 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1474 if ((!vsbin && vertstring) || (!psbin && fragstring))
1476 const char* dllnames_d3dx9 [] =
1500 dllhandle_t d3dx9_dll = NULL;
1501 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1502 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1503 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1504 dllfunction_t d3dx9_dllfuncs[] =
1506 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1507 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1508 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1511 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1513 DWORD shaderflags = 0;
1515 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1516 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1517 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1518 if (vertstring && vertstring[0])
1522 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1523 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1524 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1525 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1528 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1531 vsbinsize = vsbuffer->GetBufferSize();
1532 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1533 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1534 vsbuffer->Release();
1538 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1539 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1543 if (fragstring && fragstring[0])
1547 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1548 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1549 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1550 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1553 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1556 psbinsize = psbuffer->GetBufferSize();
1557 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1558 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1559 psbuffer->Release();
1563 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1564 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1568 Sys_UnloadLibrary(&d3dx9_dll);
1571 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1575 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1576 if (FAILED(vsresult))
1577 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1578 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1579 if (FAILED(psresult))
1580 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1582 // free the shader data
1583 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1584 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1587 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1590 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1591 int vertstring_length = 0;
1592 int geomstring_length = 0;
1593 int fragstring_length = 0;
1595 char *vertexstring, *geometrystring, *fragmentstring;
1596 char *vertstring, *geomstring, *fragstring;
1597 char permutationname[256];
1598 char cachename[256];
1599 int vertstrings_count = 0;
1600 int geomstrings_count = 0;
1601 int fragstrings_count = 0;
1602 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1603 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1604 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1609 p->vertexshader = NULL;
1610 p->pixelshader = NULL;
1612 permutationname[0] = 0;
1614 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
1615 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1616 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1618 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1619 strlcat(cachename, "hlsl/", sizeof(cachename));
1621 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1622 vertstrings_count = 0;
1623 geomstrings_count = 0;
1624 fragstrings_count = 0;
1625 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1626 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1627 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1629 // the first pretext is which type of shader to compile as
1630 // (later these will all be bound together as a program object)
1631 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1632 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1633 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1635 // the second pretext is the mode (for example a light source)
1636 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1637 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1638 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1639 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1640 strlcat(cachename, modeinfo->name, sizeof(cachename));
1642 // now add all the permutation pretexts
1643 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1645 if (permutation & (1<<i))
1647 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1648 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1649 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1650 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1651 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1655 // keep line numbers correct
1656 vertstrings_list[vertstrings_count++] = "\n";
1657 geomstrings_list[geomstrings_count++] = "\n";
1658 fragstrings_list[fragstrings_count++] = "\n";
1663 R_CompileShader_AddStaticParms(mode, permutation);
1664 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1665 vertstrings_count += shaderstaticparms_count;
1666 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1667 geomstrings_count += shaderstaticparms_count;
1668 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1669 fragstrings_count += shaderstaticparms_count;
1671 // replace spaces in the cachename with _ characters
1672 for (i = 0;cachename[i];i++)
1673 if (cachename[i] == ' ')
1676 // now append the shader text itself
1677 vertstrings_list[vertstrings_count++] = vertexstring;
1678 geomstrings_list[geomstrings_count++] = geometrystring;
1679 fragstrings_list[fragstrings_count++] = fragmentstring;
1681 // if any sources were NULL, clear the respective list
1683 vertstrings_count = 0;
1684 if (!geometrystring)
1685 geomstrings_count = 0;
1686 if (!fragmentstring)
1687 fragstrings_count = 0;
1689 vertstring_length = 0;
1690 for (i = 0;i < vertstrings_count;i++)
1691 vertstring_length += strlen(vertstrings_list[i]);
1692 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1693 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1694 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1696 geomstring_length = 0;
1697 for (i = 0;i < geomstrings_count;i++)
1698 geomstring_length += strlen(geomstrings_list[i]);
1699 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1700 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1701 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1703 fragstring_length = 0;
1704 for (i = 0;i < fragstrings_count;i++)
1705 fragstring_length += strlen(fragstrings_list[i]);
1706 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1707 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1708 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1710 // try to load the cached shader, or generate one
1711 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1713 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1714 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1716 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1720 Mem_Free(vertstring);
1722 Mem_Free(geomstring);
1724 Mem_Free(fragstring);
1726 Mem_Free(vertexstring);
1728 Mem_Free(geometrystring);
1730 Mem_Free(fragmentstring);
1733 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1734 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1735 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);}
1736 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);}
1737 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);}
1738 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);}
1740 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1741 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1742 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);}
1743 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);}
1744 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);}
1745 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);}
1747 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1749 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1750 if (r_hlsl_permutation != perm)
1752 r_hlsl_permutation = perm;
1753 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1755 if (!r_hlsl_permutation->compiled)
1756 R_HLSL_CompilePermutation(perm, mode, permutation);
1757 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1759 // remove features until we find a valid permutation
1761 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1763 // reduce i more quickly whenever it would not remove any bits
1764 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1765 if (!(permutation & j))
1768 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1769 if (!r_hlsl_permutation->compiled)
1770 R_HLSL_CompilePermutation(perm, mode, permutation);
1771 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1774 if (i >= SHADERPERMUTATION_COUNT)
1776 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1777 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1778 return; // no bit left to clear, entire mode is broken
1782 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1783 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1785 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1786 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1787 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1791 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1793 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1794 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1795 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1796 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1799 void R_GLSL_Restart_f(void)
1801 unsigned int i, limit;
1802 if (glslshaderstring && glslshaderstring != builtinshaderstring)
1803 Mem_Free(glslshaderstring);
1804 glslshaderstring = NULL;
1805 if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1806 Mem_Free(hlslshaderstring);
1807 hlslshaderstring = NULL;
1808 switch(vid.renderpath)
1810 case RENDERPATH_D3D9:
1813 r_hlsl_permutation_t *p;
1814 r_hlsl_permutation = NULL;
1815 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1816 for (i = 0;i < limit;i++)
1818 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1820 if (p->vertexshader)
1821 IDirect3DVertexShader9_Release(p->vertexshader);
1823 IDirect3DPixelShader9_Release(p->pixelshader);
1824 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1827 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1831 case RENDERPATH_D3D10:
1832 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1834 case RENDERPATH_D3D11:
1835 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1837 case RENDERPATH_GL20:
1838 case RENDERPATH_GLES2:
1840 r_glsl_permutation_t *p;
1841 r_glsl_permutation = NULL;
1842 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1843 for (i = 0;i < limit;i++)
1845 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1847 GL_Backend_FreeProgram(p->program);
1848 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1851 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1854 case RENDERPATH_GL13:
1855 case RENDERPATH_GL11:
1857 case RENDERPATH_SOFT:
1862 void R_GLSL_DumpShader_f(void)
1867 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1870 FS_Print(file, "/* The engine may define the following macros:\n");
1871 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1872 for (i = 0;i < SHADERMODE_COUNT;i++)
1873 FS_Print(file, glslshadermodeinfo[i].pretext);
1874 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1875 FS_Print(file, shaderpermutationinfo[i].pretext);
1876 FS_Print(file, "*/\n");
1877 FS_Print(file, builtinshaderstring);
1879 Con_Printf("glsl/default.glsl written\n");
1882 Con_Printf("failed to write to glsl/default.glsl\n");
1884 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1887 FS_Print(file, "/* The engine may define the following macros:\n");
1888 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1889 for (i = 0;i < SHADERMODE_COUNT;i++)
1890 FS_Print(file, hlslshadermodeinfo[i].pretext);
1891 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1892 FS_Print(file, shaderpermutationinfo[i].pretext);
1893 FS_Print(file, "*/\n");
1894 FS_Print(file, builtinhlslshaderstring);
1896 Con_Printf("hlsl/default.hlsl written\n");
1899 Con_Printf("failed to write to hlsl/default.hlsl\n");
1902 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1905 texturemode = GL_MODULATE;
1906 switch (vid.renderpath)
1908 case RENDERPATH_D3D9:
1910 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))));
1911 R_Mesh_TexBind(GL20TU_FIRST , first );
1912 R_Mesh_TexBind(GL20TU_SECOND, second);
1915 case RENDERPATH_D3D10:
1916 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1918 case RENDERPATH_D3D11:
1919 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1921 case RENDERPATH_GL20:
1922 case RENDERPATH_GLES2:
1923 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))));
1924 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1925 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1927 case RENDERPATH_GL13:
1928 R_Mesh_TexBind(0, first );
1929 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1930 R_Mesh_TexBind(1, second);
1932 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1934 case RENDERPATH_GL11:
1935 R_Mesh_TexBind(0, first );
1937 case RENDERPATH_SOFT:
1938 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))));
1939 R_Mesh_TexBind(GL20TU_FIRST , first );
1940 R_Mesh_TexBind(GL20TU_SECOND, second);
1945 void R_SetupShader_DepthOrShadow(void)
1947 switch (vid.renderpath)
1949 case RENDERPATH_D3D9:
1951 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1954 case RENDERPATH_D3D10:
1955 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1957 case RENDERPATH_D3D11:
1958 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1960 case RENDERPATH_GL20:
1961 case RENDERPATH_GLES2:
1962 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1964 case RENDERPATH_GL13:
1965 R_Mesh_TexBind(0, 0);
1966 R_Mesh_TexBind(1, 0);
1968 case RENDERPATH_GL11:
1969 R_Mesh_TexBind(0, 0);
1971 case RENDERPATH_SOFT:
1972 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1977 void R_SetupShader_ShowDepth(void)
1979 switch (vid.renderpath)
1981 case RENDERPATH_D3D9:
1983 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1986 case RENDERPATH_D3D10:
1987 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1989 case RENDERPATH_D3D11:
1990 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1992 case RENDERPATH_GL20:
1993 case RENDERPATH_GLES2:
1994 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1996 case RENDERPATH_GL13:
1998 case RENDERPATH_GL11:
2000 case RENDERPATH_SOFT:
2001 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
2006 extern qboolean r_shadow_usingdeferredprepass;
2007 extern cvar_t r_shadow_deferred_8bitrange;
2008 extern rtexture_t *r_shadow_attenuationgradienttexture;
2009 extern rtexture_t *r_shadow_attenuation2dtexture;
2010 extern rtexture_t *r_shadow_attenuation3dtexture;
2011 extern qboolean r_shadow_usingshadowmap2d;
2012 extern qboolean r_shadow_usingshadowmaportho;
2013 extern float r_shadow_shadowmap_texturescale[2];
2014 extern float r_shadow_shadowmap_parameters[4];
2015 extern qboolean r_shadow_shadowmapvsdct;
2016 extern qboolean r_shadow_shadowmapsampler;
2017 extern int r_shadow_shadowmappcf;
2018 extern rtexture_t *r_shadow_shadowmap2dtexture;
2019 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2020 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2021 extern matrix4x4_t r_shadow_shadowmapmatrix;
2022 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2023 extern int r_shadow_prepass_width;
2024 extern int r_shadow_prepass_height;
2025 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2026 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2027 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2028 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2029 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2031 #define BLENDFUNC_ALLOWS_COLORMOD 1
2032 #define BLENDFUNC_ALLOWS_FOG 2
2033 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2034 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2035 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2036 static int R_BlendFuncFlags(int src, int dst)
2040 // a blendfunc allows colormod if:
2041 // a) it can never keep the destination pixel invariant, or
2042 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2043 // this is to prevent unintended side effects from colormod
2045 // a blendfunc allows fog if:
2046 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2047 // this is to prevent unintended side effects from fog
2049 // these checks are the output of fogeval.pl
2051 r |= BLENDFUNC_ALLOWS_COLORMOD;
2052 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2053 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2054 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2055 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2056 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2057 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2058 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2059 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2060 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2061 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2062 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2063 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2064 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2065 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2066 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2067 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2068 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2069 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2070 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2071 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2072 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2077 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)
2079 // select a permutation of the lighting shader appropriate to this
2080 // combination of texture, entity, light source, and fogging, only use the
2081 // minimum features necessary to avoid wasting rendering time in the
2082 // fragment shader on features that are not being used
2083 unsigned int permutation = 0;
2084 unsigned int mode = 0;
2086 static float dummy_colormod[3] = {1, 1, 1};
2087 float *colormod = rsurface.colormod;
2089 matrix4x4_t tempmatrix;
2090 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2091 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2092 permutation |= SHADERPERMUTATION_ALPHAKILL;
2093 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2094 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2095 if (rsurfacepass == RSURFPASS_BACKGROUND)
2097 // distorted background
2098 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2100 mode = SHADERMODE_WATER;
2101 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2103 // this is the right thing to do for wateralpha
2104 GL_BlendFunc(GL_ONE, GL_ZERO);
2105 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2109 // this is the right thing to do for entity alpha
2110 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2111 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2114 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2116 mode = SHADERMODE_REFRACTION;
2117 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2118 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2122 mode = SHADERMODE_GENERIC;
2123 permutation |= SHADERPERMUTATION_DIFFUSE;
2124 GL_BlendFunc(GL_ONE, GL_ZERO);
2125 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2128 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2130 if (r_glsl_offsetmapping.integer)
2132 switch(rsurface.texture->offsetmapping)
2134 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2135 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2136 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2137 case OFFSETMAPPING_OFF: break;
2140 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2141 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2142 // normalmap (deferred prepass), may use alpha test on diffuse
2143 mode = SHADERMODE_DEFERREDGEOMETRY;
2144 GL_BlendFunc(GL_ONE, GL_ZERO);
2145 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2147 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2149 if (r_glsl_offsetmapping.integer)
2151 switch(rsurface.texture->offsetmapping)
2153 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2154 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2155 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2156 case OFFSETMAPPING_OFF: break;
2159 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2160 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2162 mode = SHADERMODE_LIGHTSOURCE;
2163 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2164 permutation |= SHADERPERMUTATION_CUBEFILTER;
2165 if (diffusescale > 0)
2166 permutation |= SHADERPERMUTATION_DIFFUSE;
2167 if (specularscale > 0)
2168 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2169 if (r_refdef.fogenabled)
2170 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2171 if (rsurface.texture->colormapping)
2172 permutation |= SHADERPERMUTATION_COLORMAPPING;
2173 if (r_shadow_usingshadowmap2d)
2175 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2176 if(r_shadow_shadowmapvsdct)
2177 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2179 if (r_shadow_shadowmapsampler)
2180 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2181 if (r_shadow_shadowmappcf > 1)
2182 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2183 else if (r_shadow_shadowmappcf)
2184 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2186 if (rsurface.texture->reflectmasktexture)
2187 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2188 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2189 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2191 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2193 if (r_glsl_offsetmapping.integer)
2195 switch(rsurface.texture->offsetmapping)
2197 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2198 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2199 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2200 case OFFSETMAPPING_OFF: break;
2203 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2204 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2205 // unshaded geometry (fullbright or ambient model lighting)
2206 mode = SHADERMODE_FLATCOLOR;
2207 ambientscale = diffusescale = specularscale = 0;
2208 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2209 permutation |= SHADERPERMUTATION_GLOW;
2210 if (r_refdef.fogenabled)
2211 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2212 if (rsurface.texture->colormapping)
2213 permutation |= SHADERPERMUTATION_COLORMAPPING;
2214 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2216 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2217 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2219 if (r_shadow_shadowmapsampler)
2220 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2221 if (r_shadow_shadowmappcf > 1)
2222 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2223 else if (r_shadow_shadowmappcf)
2224 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2226 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2227 permutation |= SHADERPERMUTATION_REFLECTION;
2228 if (rsurface.texture->reflectmasktexture)
2229 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2230 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2231 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2233 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2235 if (r_glsl_offsetmapping.integer)
2237 switch(rsurface.texture->offsetmapping)
2239 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2240 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2241 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2242 case OFFSETMAPPING_OFF: break;
2245 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2246 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2247 // directional model lighting
2248 mode = SHADERMODE_LIGHTDIRECTION;
2249 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2250 permutation |= SHADERPERMUTATION_GLOW;
2251 permutation |= SHADERPERMUTATION_DIFFUSE;
2252 if (specularscale > 0)
2253 permutation |= SHADERPERMUTATION_SPECULAR;
2254 if (r_refdef.fogenabled)
2255 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2256 if (rsurface.texture->colormapping)
2257 permutation |= SHADERPERMUTATION_COLORMAPPING;
2258 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2260 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2261 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2263 if (r_shadow_shadowmapsampler)
2264 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2265 if (r_shadow_shadowmappcf > 1)
2266 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2267 else if (r_shadow_shadowmappcf)
2268 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2270 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2271 permutation |= SHADERPERMUTATION_REFLECTION;
2272 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2273 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2274 if (rsurface.texture->reflectmasktexture)
2275 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2276 if (r_shadow_bouncegridtexture)
2278 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2279 if (r_shadow_bouncegriddirectional)
2280 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2282 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2283 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2285 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2287 if (r_glsl_offsetmapping.integer)
2289 switch(rsurface.texture->offsetmapping)
2291 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2292 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2293 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2294 case OFFSETMAPPING_OFF: break;
2297 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2298 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2299 // ambient model lighting
2300 mode = SHADERMODE_LIGHTDIRECTION;
2301 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2302 permutation |= SHADERPERMUTATION_GLOW;
2303 if (r_refdef.fogenabled)
2304 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2305 if (rsurface.texture->colormapping)
2306 permutation |= SHADERPERMUTATION_COLORMAPPING;
2307 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2309 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2310 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2312 if (r_shadow_shadowmapsampler)
2313 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2314 if (r_shadow_shadowmappcf > 1)
2315 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2316 else if (r_shadow_shadowmappcf)
2317 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2319 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2320 permutation |= SHADERPERMUTATION_REFLECTION;
2321 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2322 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2323 if (rsurface.texture->reflectmasktexture)
2324 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2325 if (r_shadow_bouncegridtexture)
2327 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2328 if (r_shadow_bouncegriddirectional)
2329 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2331 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2332 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2336 if (r_glsl_offsetmapping.integer)
2338 switch(rsurface.texture->offsetmapping)
2340 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2341 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2342 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2343 case OFFSETMAPPING_OFF: break;
2346 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2347 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2349 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2350 permutation |= SHADERPERMUTATION_GLOW;
2351 if (r_refdef.fogenabled)
2352 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2353 if (rsurface.texture->colormapping)
2354 permutation |= SHADERPERMUTATION_COLORMAPPING;
2355 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2357 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2358 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2360 if (r_shadow_shadowmapsampler)
2361 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2362 if (r_shadow_shadowmappcf > 1)
2363 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2364 else if (r_shadow_shadowmappcf)
2365 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2367 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2368 permutation |= SHADERPERMUTATION_REFLECTION;
2369 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2370 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2371 if (rsurface.texture->reflectmasktexture)
2372 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2373 if (FAKELIGHT_ENABLED)
2375 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2376 mode = SHADERMODE_FAKELIGHT;
2377 permutation |= SHADERPERMUTATION_DIFFUSE;
2378 if (specularscale > 0)
2379 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2381 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2383 // deluxemapping (light direction texture)
2384 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2385 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2387 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2388 permutation |= SHADERPERMUTATION_DIFFUSE;
2389 if (specularscale > 0)
2390 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2392 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2394 // fake deluxemapping (uniform light direction in tangentspace)
2395 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2396 permutation |= SHADERPERMUTATION_DIFFUSE;
2397 if (specularscale > 0)
2398 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2400 else if (rsurface.uselightmaptexture)
2402 // ordinary lightmapping (q1bsp, q3bsp)
2403 mode = SHADERMODE_LIGHTMAP;
2407 // ordinary vertex coloring (q3bsp)
2408 mode = SHADERMODE_VERTEXCOLOR;
2410 if (r_shadow_bouncegridtexture)
2412 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2413 if (r_shadow_bouncegriddirectional)
2414 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2416 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2417 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2419 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2420 colormod = dummy_colormod;
2421 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2422 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2423 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2424 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2425 switch(vid.renderpath)
2427 case RENDERPATH_D3D9:
2429 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);
2430 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2431 R_SetupShader_SetPermutationHLSL(mode, permutation);
2432 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2433 if (mode == SHADERMODE_LIGHTSOURCE)
2435 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2436 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2440 if (mode == SHADERMODE_LIGHTDIRECTION)
2442 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2445 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2446 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2447 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2448 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2449 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2451 if (mode == SHADERMODE_LIGHTSOURCE)
2453 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2454 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2455 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2456 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2457 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2459 // additive passes are only darkened by fog, not tinted
2460 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2461 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2465 if (mode == SHADERMODE_FLATCOLOR)
2467 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2469 else if (mode == SHADERMODE_LIGHTDIRECTION)
2471 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]);
2472 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2473 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);
2474 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);
2475 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2476 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2477 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2481 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2482 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2483 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);
2484 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);
2485 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2487 // additive passes are only darkened by fog, not tinted
2488 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2489 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2491 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2492 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);
2493 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2494 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2495 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2496 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2497 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2498 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2499 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2500 if (mode == SHADERMODE_WATER)
2501 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2503 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2504 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2505 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2506 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));
2507 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2508 if (rsurface.texture->pantstexture)
2509 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2511 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2512 if (rsurface.texture->shirttexture)
2513 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2515 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2516 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2517 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2518 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2519 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2520 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));
2521 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2522 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2524 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2525 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2526 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2527 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2528 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2529 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2530 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2531 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2532 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2533 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2534 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2535 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2536 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2537 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2538 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2539 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2540 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2541 if (rsurfacepass == RSURFPASS_BACKGROUND)
2543 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2544 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2545 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2549 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2551 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2552 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2553 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2554 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2555 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2557 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2558 if (rsurface.rtlight)
2560 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2561 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2566 case RENDERPATH_D3D10:
2567 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2569 case RENDERPATH_D3D11:
2570 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2572 case RENDERPATH_GL20:
2573 case RENDERPATH_GLES2:
2574 if (!vid.useinterleavedarrays)
2576 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);
2577 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2578 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2579 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2580 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2581 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2582 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2583 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2587 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);
2588 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2590 R_SetupShader_SetPermutationGLSL(mode, permutation);
2591 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2592 if (mode == SHADERMODE_LIGHTSOURCE)
2594 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2595 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2596 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2597 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2598 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2599 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);
2601 // additive passes are only darkened by fog, not tinted
2602 if (r_glsl_permutation->loc_FogColor >= 0)
2603 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2604 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2608 if (mode == SHADERMODE_FLATCOLOR)
2610 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2612 else if (mode == SHADERMODE_LIGHTDIRECTION)
2614 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]);
2615 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]);
2616 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);
2617 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);
2618 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);
2619 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]);
2620 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]);
2624 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]);
2625 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]);
2626 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);
2627 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);
2628 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);
2630 // additive passes are only darkened by fog, not tinted
2631 if (r_glsl_permutation->loc_FogColor >= 0)
2633 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2634 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2636 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2638 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);
2639 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]);
2640 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]);
2641 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]);
2642 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]);
2643 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2644 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2645 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2646 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]);
2648 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2649 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2650 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2651 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]);
2652 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]);
2654 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2655 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));
2656 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2657 if (r_glsl_permutation->loc_Color_Pants >= 0)
2659 if (rsurface.texture->pantstexture)
2660 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2662 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2664 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2666 if (rsurface.texture->shirttexture)
2667 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2669 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2671 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]);
2672 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2673 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2674 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2675 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));
2676 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]);
2677 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2678 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);}
2679 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2681 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2682 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2683 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2684 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2685 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2686 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2687 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2688 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2689 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2690 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2691 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2692 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2693 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2694 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2695 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);
2696 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2697 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2698 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2699 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2700 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2701 if (rsurfacepass == RSURFPASS_BACKGROUND)
2703 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);
2704 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);
2705 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);
2709 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);
2711 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2712 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2713 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2714 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2715 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2717 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
2718 if (rsurface.rtlight)
2720 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2721 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2724 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2727 case RENDERPATH_GL13:
2728 case RENDERPATH_GL11:
2730 case RENDERPATH_SOFT:
2731 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);
2732 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2733 R_SetupShader_SetPermutationSoft(mode, permutation);
2734 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2735 if (mode == SHADERMODE_LIGHTSOURCE)
2737 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2738 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2739 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2740 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2741 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2742 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2744 // additive passes are only darkened by fog, not tinted
2745 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2746 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2750 if (mode == SHADERMODE_FLATCOLOR)
2752 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2754 else if (mode == SHADERMODE_LIGHTDIRECTION)
2756 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]);
2757 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2758 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);
2759 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);
2760 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2761 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]);
2762 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2766 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2767 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2768 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);
2769 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);
2770 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2772 // additive passes are only darkened by fog, not tinted
2773 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2774 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2776 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2777 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);
2778 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2779 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2780 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]);
2781 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]);
2782 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2783 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2784 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2785 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2787 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2788 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2789 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2790 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2791 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]);
2793 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2794 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));
2795 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2796 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2798 if (rsurface.texture->pantstexture)
2799 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2801 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2803 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2805 if (rsurface.texture->shirttexture)
2806 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2808 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2810 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2811 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2812 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2813 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2814 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));
2815 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2816 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2818 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2819 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2820 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2821 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2822 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2823 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2824 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2825 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2826 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2827 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2828 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2829 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2830 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2831 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2832 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2833 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2834 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2835 if (rsurfacepass == RSURFPASS_BACKGROUND)
2837 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2838 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2839 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2843 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2845 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2846 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2847 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2848 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2849 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2851 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2852 if (rsurface.rtlight)
2854 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2855 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2862 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2864 // select a permutation of the lighting shader appropriate to this
2865 // combination of texture, entity, light source, and fogging, only use the
2866 // minimum features necessary to avoid wasting rendering time in the
2867 // fragment shader on features that are not being used
2868 unsigned int permutation = 0;
2869 unsigned int mode = 0;
2870 const float *lightcolorbase = rtlight->currentcolor;
2871 float ambientscale = rtlight->ambientscale;
2872 float diffusescale = rtlight->diffusescale;
2873 float specularscale = rtlight->specularscale;
2874 // this is the location of the light in view space
2875 vec3_t viewlightorigin;
2876 // this transforms from view space (camera) to light space (cubemap)
2877 matrix4x4_t viewtolight;
2878 matrix4x4_t lighttoview;
2879 float viewtolight16f[16];
2880 float range = 1.0f / r_shadow_deferred_8bitrange.value;
2882 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2883 if (rtlight->currentcubemap != r_texture_whitecube)
2884 permutation |= SHADERPERMUTATION_CUBEFILTER;
2885 if (diffusescale > 0)
2886 permutation |= SHADERPERMUTATION_DIFFUSE;
2887 if (specularscale > 0 && r_shadow_gloss.integer > 0)
2888 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2889 if (r_shadow_usingshadowmap2d)
2891 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2892 if (r_shadow_shadowmapvsdct)
2893 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2895 if (r_shadow_shadowmapsampler)
2896 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2897 if (r_shadow_shadowmappcf > 1)
2898 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2899 else if (r_shadow_shadowmappcf)
2900 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2902 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2903 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2904 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2905 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2906 switch(vid.renderpath)
2908 case RENDERPATH_D3D9:
2910 R_SetupShader_SetPermutationHLSL(mode, permutation);
2911 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2912 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2913 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2914 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2915 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2916 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2917 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2918 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2919 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2920 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2922 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2923 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
2924 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2925 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2926 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
2927 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2930 case RENDERPATH_D3D10:
2931 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2933 case RENDERPATH_D3D11:
2934 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2936 case RENDERPATH_GL20:
2937 case RENDERPATH_GLES2:
2938 R_SetupShader_SetPermutationGLSL(mode, permutation);
2939 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2940 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
2941 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);
2942 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);
2943 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);
2944 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]);
2945 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]);
2946 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));
2947 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]);
2948 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
2950 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2951 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2952 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2953 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2954 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
2955 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2957 case RENDERPATH_GL13:
2958 case RENDERPATH_GL11:
2960 case RENDERPATH_SOFT:
2961 R_SetupShader_SetPermutationGLSL(mode, permutation);
2962 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2963 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
2964 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2965 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2966 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2967 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2968 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]);
2969 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));
2970 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2971 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2973 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2974 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2975 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2976 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2977 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
2978 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2983 #define SKINFRAME_HASH 1024
2987 int loadsequence; // incremented each level change
2988 memexpandablearray_t array;
2989 skinframe_t *hash[SKINFRAME_HASH];
2992 r_skinframe_t r_skinframe;
2994 void R_SkinFrame_PrepareForPurge(void)
2996 r_skinframe.loadsequence++;
2997 // wrap it without hitting zero
2998 if (r_skinframe.loadsequence >= 200)
2999 r_skinframe.loadsequence = 1;
3002 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3006 // mark the skinframe as used for the purging code
3007 skinframe->loadsequence = r_skinframe.loadsequence;
3010 void R_SkinFrame_Purge(void)
3014 for (i = 0;i < SKINFRAME_HASH;i++)
3016 for (s = r_skinframe.hash[i];s;s = s->next)
3018 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3020 if (s->merged == s->base)
3022 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3023 R_PurgeTexture(s->stain );s->stain = NULL;
3024 R_PurgeTexture(s->merged);s->merged = NULL;
3025 R_PurgeTexture(s->base );s->base = NULL;
3026 R_PurgeTexture(s->pants );s->pants = NULL;
3027 R_PurgeTexture(s->shirt );s->shirt = NULL;
3028 R_PurgeTexture(s->nmap );s->nmap = NULL;
3029 R_PurgeTexture(s->gloss );s->gloss = NULL;
3030 R_PurgeTexture(s->glow );s->glow = NULL;
3031 R_PurgeTexture(s->fog );s->fog = NULL;
3032 R_PurgeTexture(s->reflect);s->reflect = NULL;
3033 s->loadsequence = 0;
3039 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3041 char basename[MAX_QPATH];
3043 Image_StripImageExtension(name, basename, sizeof(basename));
3045 if( last == NULL ) {
3047 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3048 item = r_skinframe.hash[hashindex];
3053 // linearly search through the hash bucket
3054 for( ; item ; item = item->next ) {
3055 if( !strcmp( item->basename, basename ) ) {
3062 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3066 char basename[MAX_QPATH];
3068 Image_StripImageExtension(name, basename, sizeof(basename));
3070 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3071 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3072 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3076 rtexture_t *dyntexture;
3077 // check whether its a dynamic texture
3078 dyntexture = CL_GetDynTexture( basename );
3079 if (!add && !dyntexture)
3081 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3082 memset(item, 0, sizeof(*item));
3083 strlcpy(item->basename, basename, sizeof(item->basename));
3084 item->base = dyntexture; // either NULL or dyntexture handle
3085 item->textureflags = textureflags;
3086 item->comparewidth = comparewidth;
3087 item->compareheight = compareheight;
3088 item->comparecrc = comparecrc;
3089 item->next = r_skinframe.hash[hashindex];
3090 r_skinframe.hash[hashindex] = item;
3092 else if( item->base == NULL )
3094 rtexture_t *dyntexture;
3095 // check whether its a dynamic texture
3096 // 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]
3097 dyntexture = CL_GetDynTexture( basename );
3098 item->base = dyntexture; // either NULL or dyntexture handle
3101 R_SkinFrame_MarkUsed(item);
3105 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3107 unsigned long long avgcolor[5], wsum; \
3115 for(pix = 0; pix < cnt; ++pix) \
3118 for(comp = 0; comp < 3; ++comp) \
3120 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3123 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3125 for(comp = 0; comp < 3; ++comp) \
3126 avgcolor[comp] += getpixel * w; \
3129 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3130 avgcolor[4] += getpixel; \
3132 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3134 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3135 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3136 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3137 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3140 extern cvar_t gl_picmip;
3141 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3144 unsigned char *pixels;
3145 unsigned char *bumppixels;
3146 unsigned char *basepixels = NULL;
3147 int basepixels_width = 0;
3148 int basepixels_height = 0;
3149 skinframe_t *skinframe;
3150 rtexture_t *ddsbase = NULL;
3151 qboolean ddshasalpha = false;
3152 float ddsavgcolor[4];
3153 char basename[MAX_QPATH];
3154 int miplevel = R_PicmipForFlags(textureflags);
3155 int savemiplevel = miplevel;
3158 if (cls.state == ca_dedicated)
3161 // return an existing skinframe if already loaded
3162 // if loading of the first image fails, don't make a new skinframe as it
3163 // would cause all future lookups of this to be missing
3164 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3165 if (skinframe && skinframe->base)
3168 Image_StripImageExtension(name, basename, sizeof(basename));
3170 // check for DDS texture file first
3171 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3173 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3174 if (basepixels == NULL)
3178 // FIXME handle miplevel
3180 if (developer_loading.integer)
3181 Con_Printf("loading skin \"%s\"\n", name);
3183 // we've got some pixels to store, so really allocate this new texture now
3185 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3186 skinframe->stain = NULL;
3187 skinframe->merged = NULL;
3188 skinframe->base = NULL;
3189 skinframe->pants = NULL;
3190 skinframe->shirt = NULL;
3191 skinframe->nmap = NULL;
3192 skinframe->gloss = NULL;
3193 skinframe->glow = NULL;
3194 skinframe->fog = NULL;
3195 skinframe->reflect = NULL;
3196 skinframe->hasalpha = false;
3200 skinframe->base = ddsbase;
3201 skinframe->hasalpha = ddshasalpha;
3202 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3203 if (r_loadfog && skinframe->hasalpha)
3204 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3205 //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]);
3209 basepixels_width = image_width;
3210 basepixels_height = image_height;
3211 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, r_texture_sRGB_skin_diffuse.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3212 if (textureflags & TEXF_ALPHA)
3214 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3216 if (basepixels[j] < 255)
3218 skinframe->hasalpha = true;
3222 if (r_loadfog && skinframe->hasalpha)
3224 // has transparent pixels
3225 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3226 for (j = 0;j < image_width * image_height * 4;j += 4)
3231 pixels[j+3] = basepixels[j+3];
3233 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);
3237 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3238 //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]);
3239 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3240 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
3241 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3242 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
3247 mymiplevel = savemiplevel;
3248 if (r_loadnormalmap)
3249 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);
3250 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3252 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3253 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3254 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3255 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3258 // _norm is the name used by tenebrae and has been adopted as standard
3259 if (r_loadnormalmap && skinframe->nmap == NULL)
3261 mymiplevel = savemiplevel;
3262 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3264 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);
3268 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3270 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3271 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3272 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);
3274 Mem_Free(bumppixels);
3276 else if (r_shadow_bumpscale_basetexture.value > 0)
3278 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3279 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3280 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);
3283 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3284 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
3287 // _luma is supported only for tenebrae compatibility
3288 // _glow is the preferred name
3289 mymiplevel = savemiplevel;
3290 if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false, false, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, false, &mymiplevel))))
3292 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, r_texture_sRGB_skin_glow.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3293 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3294 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
3295 Mem_Free(pixels);pixels = NULL;
3298 mymiplevel = savemiplevel;
3299 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3301 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, r_texture_sRGB_skin_gloss.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3302 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3303 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
3308 mymiplevel = savemiplevel;
3309 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3311 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, r_texture_sRGB_skin_diffuse.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3312 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3313 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
3318 mymiplevel = savemiplevel;
3319 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3321 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, r_texture_sRGB_skin_diffuse.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3322 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3323 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
3328 mymiplevel = savemiplevel;
3329 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3331 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, r_texture_sRGB_skin_reflect.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3332 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3333 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
3339 Mem_Free(basepixels);
3344 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3345 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3348 unsigned char *temp1, *temp2;
3349 skinframe_t *skinframe;
3351 if (cls.state == ca_dedicated)
3354 // if already loaded just return it, otherwise make a new skinframe
3355 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3356 if (skinframe && skinframe->base)
3359 skinframe->stain = NULL;
3360 skinframe->merged = NULL;
3361 skinframe->base = NULL;
3362 skinframe->pants = NULL;
3363 skinframe->shirt = NULL;
3364 skinframe->nmap = NULL;
3365 skinframe->gloss = NULL;
3366 skinframe->glow = NULL;
3367 skinframe->fog = NULL;
3368 skinframe->reflect = NULL;
3369 skinframe->hasalpha = false;
3371 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3375 if (developer_loading.integer)
3376 Con_Printf("loading 32bit skin \"%s\"\n", name);
3378 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3380 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3381 temp2 = temp1 + width * height * 4;
3382 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3383 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);
3386 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3387 if (textureflags & TEXF_ALPHA)
3389 for (i = 3;i < width * height * 4;i += 4)
3391 if (skindata[i] < 255)
3393 skinframe->hasalpha = true;
3397 if (r_loadfog && skinframe->hasalpha)
3399 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3400 memcpy(fogpixels, skindata, width * height * 4);
3401 for (i = 0;i < width * height * 4;i += 4)
3402 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3403 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3404 Mem_Free(fogpixels);
3408 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3409 //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]);
3414 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3418 skinframe_t *skinframe;
3420 if (cls.state == ca_dedicated)
3423 // if already loaded just return it, otherwise make a new skinframe
3424 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3425 if (skinframe && skinframe->base)
3428 skinframe->stain = NULL;
3429 skinframe->merged = NULL;
3430 skinframe->base = NULL;
3431 skinframe->pants = NULL;
3432 skinframe->shirt = NULL;
3433 skinframe->nmap = NULL;
3434 skinframe->gloss = NULL;
3435 skinframe->glow = NULL;
3436 skinframe->fog = NULL;
3437 skinframe->reflect = NULL;
3438 skinframe->hasalpha = false;
3440 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3444 if (developer_loading.integer)
3445 Con_Printf("loading quake skin \"%s\"\n", name);
3447 // 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)
3448 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3449 memcpy(skinframe->qpixels, skindata, width*height);
3450 skinframe->qwidth = width;
3451 skinframe->qheight = height;
3454 for (i = 0;i < width * height;i++)
3455 featuresmask |= palette_featureflags[skindata[i]];
3457 skinframe->hasalpha = false;
3458 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3459 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3460 skinframe->qgeneratemerged = true;
3461 skinframe->qgeneratebase = skinframe->qhascolormapping;
3462 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3464 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3465 //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]);
3470 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3474 unsigned char *skindata;
3476 if (!skinframe->qpixels)
3479 if (!skinframe->qhascolormapping)
3480 colormapped = false;
3484 if (!skinframe->qgeneratebase)
3489 if (!skinframe->qgeneratemerged)
3493 width = skinframe->qwidth;
3494 height = skinframe->qheight;
3495 skindata = skinframe->qpixels;
3497 if (skinframe->qgeneratenmap)
3499 unsigned char *temp1, *temp2;
3500 skinframe->qgeneratenmap = false;
3501 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3502 temp2 = temp1 + width * height * 4;
3503 // use either a custom palette or the quake palette
3504 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3505 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3506 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);
3510 if (skinframe->qgenerateglow)
3512 skinframe->qgenerateglow = false;
3513 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3518 skinframe->qgeneratebase = false;
3519 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);
3520 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3521 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3525 skinframe->qgeneratemerged = false;
3526 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);
3529 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3531 Mem_Free(skinframe->qpixels);
3532 skinframe->qpixels = NULL;
3536 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)
3539 skinframe_t *skinframe;
3541 if (cls.state == ca_dedicated)
3544 // if already loaded just return it, otherwise make a new skinframe
3545 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3546 if (skinframe && skinframe->base)
3549 skinframe->stain = NULL;
3550 skinframe->merged = NULL;
3551 skinframe->base = NULL;
3552 skinframe->pants = NULL;
3553 skinframe->shirt = NULL;
3554 skinframe->nmap = NULL;
3555 skinframe->gloss = NULL;
3556 skinframe->glow = NULL;
3557 skinframe->fog = NULL;
3558 skinframe->reflect = NULL;
3559 skinframe->hasalpha = false;
3561 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3565 if (developer_loading.integer)
3566 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3568 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3569 if (textureflags & TEXF_ALPHA)
3571 for (i = 0;i < width * height;i++)
3573 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3575 skinframe->hasalpha = true;
3579 if (r_loadfog && skinframe->hasalpha)
3580 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3583 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3584 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3589 skinframe_t *R_SkinFrame_LoadMissing(void)
3591 skinframe_t *skinframe;
3593 if (cls.state == ca_dedicated)
3596 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3597 skinframe->stain = NULL;
3598 skinframe->merged = NULL;
3599 skinframe->base = NULL;
3600 skinframe->pants = NULL;
3601 skinframe->shirt = NULL;
3602 skinframe->nmap = NULL;
3603 skinframe->gloss = NULL;
3604 skinframe->glow = NULL;
3605 skinframe->fog = NULL;
3606 skinframe->reflect = NULL;
3607 skinframe->hasalpha = false;
3609 skinframe->avgcolor[0] = rand() / RAND_MAX;
3610 skinframe->avgcolor[1] = rand() / RAND_MAX;
3611 skinframe->avgcolor[2] = rand() / RAND_MAX;
3612 skinframe->avgcolor[3] = 1;
3617 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3618 typedef struct suffixinfo_s
3621 qboolean flipx, flipy, flipdiagonal;
3624 static suffixinfo_t suffix[3][6] =
3627 {"px", false, false, false},
3628 {"nx", false, false, false},
3629 {"py", false, false, false},
3630 {"ny", false, false, false},
3631 {"pz", false, false, false},
3632 {"nz", false, false, false}
3635 {"posx", false, false, false},
3636 {"negx", false, false, false},
3637 {"posy", false, false, false},
3638 {"negy", false, false, false},
3639 {"posz", false, false, false},
3640 {"negz", false, false, false}
3643 {"rt", true, false, true},
3644 {"lf", false, true, true},
3645 {"ft", true, true, false},
3646 {"bk", false, false, false},
3647 {"up", true, false, true},
3648 {"dn", true, false, true}
3652 static int componentorder[4] = {0, 1, 2, 3};
3654 rtexture_t *R_LoadCubemap(const char *basename)
3656 int i, j, cubemapsize;
3657 unsigned char *cubemappixels, *image_buffer;
3658 rtexture_t *cubemaptexture;
3660 // must start 0 so the first loadimagepixels has no requested width/height
3662 cubemappixels = NULL;
3663 cubemaptexture = NULL;
3664 // keep trying different suffix groups (posx, px, rt) until one loads
3665 for (j = 0;j < 3 && !cubemappixels;j++)
3667 // load the 6 images in the suffix group
3668 for (i = 0;i < 6;i++)
3670 // generate an image name based on the base and and suffix
3671 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3673 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3675 // an image loaded, make sure width and height are equal
3676 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3678 // if this is the first image to load successfully, allocate the cubemap memory
3679 if (!cubemappixels && image_width >= 1)
3681 cubemapsize = image_width;
3682 // note this clears to black, so unavailable sides are black
3683 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3685 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3687 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);
3690 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3692 Mem_Free(image_buffer);
3696 // if a cubemap loaded, upload it
3699 if (developer_loading.integer)
3700 Con_Printf("loading cubemap \"%s\"\n", basename);
3702 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, r_texture_sRGB_cubemap.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3703 Mem_Free(cubemappixels);
3707 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3708 if (developer_loading.integer)
3710 Con_Printf("(tried tried images ");
3711 for (j = 0;j < 3;j++)
3712 for (i = 0;i < 6;i++)
3713 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3714 Con_Print(" and was unable to find any of them).\n");
3717 return cubemaptexture;
3720 rtexture_t *R_GetCubemap(const char *basename)
3723 for (i = 0;i < r_texture_numcubemaps;i++)
3724 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3725 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3726 if (i >= MAX_CUBEMAPS)
3727 return r_texture_whitecube;
3728 r_texture_numcubemaps++;
3729 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3730 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3731 return r_texture_cubemaps[i].texture;
3734 void R_FreeCubemaps(void)
3737 for (i = 0;i < r_texture_numcubemaps;i++)
3739 if (developer_loading.integer)
3740 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3741 if (r_texture_cubemaps[i].texture)
3742 R_FreeTexture(r_texture_cubemaps[i].texture);
3744 r_texture_numcubemaps = 0;
3747 void R_Main_FreeViewCache(void)
3749 if (r_refdef.viewcache.entityvisible)
3750 Mem_Free(r_refdef.viewcache.entityvisible);
3751 if (r_refdef.viewcache.world_pvsbits)
3752 Mem_Free(r_refdef.viewcache.world_pvsbits);
3753 if (r_refdef.viewcache.world_leafvisible)
3754 Mem_Free(r_refdef.viewcache.world_leafvisible);
3755 if (r_refdef.viewcache.world_surfacevisible)
3756 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3757 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3760 void R_Main_ResizeViewCache(void)
3762 int numentities = r_refdef.scene.numentities;
3763 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3764 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3765 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3766 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3767 if (r_refdef.viewcache.maxentities < numentities)
3769 r_refdef.viewcache.maxentities = numentities;
3770 if (r_refdef.viewcache.entityvisible)
3771 Mem_Free(r_refdef.viewcache.entityvisible);
3772 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3774 if (r_refdef.viewcache.world_numclusters != numclusters)
3776 r_refdef.viewcache.world_numclusters = numclusters;
3777 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3778 if (r_refdef.viewcache.world_pvsbits)
3779 Mem_Free(r_refdef.viewcache.world_pvsbits);
3780 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3782 if (r_refdef.viewcache.world_numleafs != numleafs)
3784 r_refdef.viewcache.world_numleafs = numleafs;
3785 if (r_refdef.viewcache.world_leafvisible)
3786 Mem_Free(r_refdef.viewcache.world_leafvisible);
3787 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3789 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3791 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3792 if (r_refdef.viewcache.world_surfacevisible)
3793 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3794 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3798 extern rtexture_t *loadingscreentexture;
3799 void gl_main_start(void)
3801 loadingscreentexture = NULL;
3802 r_texture_blanknormalmap = NULL;
3803 r_texture_white = NULL;
3804 r_texture_grey128 = NULL;
3805 r_texture_black = NULL;
3806 r_texture_whitecube = NULL;
3807 r_texture_normalizationcube = NULL;
3808 r_texture_fogattenuation = NULL;
3809 r_texture_fogheighttexture = NULL;
3810 r_texture_gammaramps = NULL;
3811 r_texture_numcubemaps = 0;
3813 r_loaddds = r_texture_dds_load.integer != 0;
3814 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3816 switch(vid.renderpath)
3818 case RENDERPATH_GL20:
3819 case RENDERPATH_D3D9:
3820 case RENDERPATH_D3D10:
3821 case RENDERPATH_D3D11:
3822 case RENDERPATH_SOFT:
3823 case RENDERPATH_GLES2:
3824 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3825 Cvar_SetValueQuick(&gl_combine, 1);
3826 Cvar_SetValueQuick(&r_glsl, 1);
3827 r_loadnormalmap = true;
3831 case RENDERPATH_GL13:
3832 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3833 Cvar_SetValueQuick(&gl_combine, 1);
3834 Cvar_SetValueQuick(&r_glsl, 0);
3835 r_loadnormalmap = false;
3836 r_loadgloss = false;
3839 case RENDERPATH_GL11:
3840 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3841 Cvar_SetValueQuick(&gl_combine, 0);
3842 Cvar_SetValueQuick(&r_glsl, 0);
3843 r_loadnormalmap = false;
3844 r_loadgloss = false;
3850 R_FrameData_Reset();
3854 memset(r_queries, 0, sizeof(r_queries));
3856 r_qwskincache = NULL;
3857 r_qwskincache_size = 0;
3859 // due to caching of texture_t references, the collision cache must be reset
3860 Collision_Cache_Reset(true);
3862 // set up r_skinframe loading system for textures
3863 memset(&r_skinframe, 0, sizeof(r_skinframe));
3864 r_skinframe.loadsequence = 1;
3865 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3867 r_main_texturepool = R_AllocTexturePool();
3868 R_BuildBlankTextures();
3870 if (vid.support.arb_texture_cube_map)
3873 R_BuildNormalizationCube();
3875 r_texture_fogattenuation = NULL;
3876 r_texture_fogheighttexture = NULL;
3877 r_texture_gammaramps = NULL;
3878 //r_texture_fogintensity = NULL;
3879 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3880 memset(&r_waterstate, 0, sizeof(r_waterstate));
3881 r_glsl_permutation = NULL;
3882 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3883 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3884 glslshaderstring = NULL;
3886 r_hlsl_permutation = NULL;
3887 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3888 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3890 hlslshaderstring = NULL;
3891 memset(&r_svbsp, 0, sizeof (r_svbsp));
3893 r_refdef.fogmasktable_density = 0;
3896 void gl_main_shutdown(void)
3899 R_FrameData_Reset();
3901 R_Main_FreeViewCache();
3903 switch(vid.renderpath)
3905 case RENDERPATH_GL11:
3906 case RENDERPATH_GL13:
3907 case RENDERPATH_GL20:
3908 case RENDERPATH_GLES2:
3910 qglDeleteQueriesARB(r_maxqueries, r_queries);
3912 case RENDERPATH_D3D9:
3913 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3915 case RENDERPATH_D3D10:
3916 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3918 case RENDERPATH_D3D11:
3919 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3921 case RENDERPATH_SOFT:
3927 memset(r_queries, 0, sizeof(r_queries));
3929 r_qwskincache = NULL;
3930 r_qwskincache_size = 0;
3932 // clear out the r_skinframe state
3933 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3934 memset(&r_skinframe, 0, sizeof(r_skinframe));
3937 Mem_Free(r_svbsp.nodes);
3938 memset(&r_svbsp, 0, sizeof (r_svbsp));
3939 R_FreeTexturePool(&r_main_texturepool);
3940 loadingscreentexture = NULL;
3941 r_texture_blanknormalmap = NULL;
3942 r_texture_white = NULL;
3943 r_texture_grey128 = NULL;
3944 r_texture_black = NULL;
3945 r_texture_whitecube = NULL;
3946 r_texture_normalizationcube = NULL;
3947 r_texture_fogattenuation = NULL;
3948 r_texture_fogheighttexture = NULL;
3949 r_texture_gammaramps = NULL;
3950 r_texture_numcubemaps = 0;
3951 //r_texture_fogintensity = NULL;
3952 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3953 memset(&r_waterstate, 0, sizeof(r_waterstate));
3956 r_glsl_permutation = NULL;
3957 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3958 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3959 glslshaderstring = NULL;
3961 r_hlsl_permutation = NULL;
3962 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3963 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3965 hlslshaderstring = NULL;
3968 extern void CL_ParseEntityLump(char *entitystring);
3969 void gl_main_newmap(void)
3971 // FIXME: move this code to client
3972 char *entities, entname[MAX_QPATH];
3974 Mem_Free(r_qwskincache);
3975 r_qwskincache = NULL;
3976 r_qwskincache_size = 0;
3979 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
3980 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
3982 CL_ParseEntityLump(entities);
3986 if (cl.worldmodel->brush.entities)
3987 CL_ParseEntityLump(cl.worldmodel->brush.entities);
3989 R_Main_FreeViewCache();
3991 R_FrameData_Reset();
3994 void GL_Main_Init(void)
3996 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
3998 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
3999 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4000 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4001 if (gamemode == GAME_NEHAHRA)
4003 Cvar_RegisterVariable (&gl_fogenable);
4004 Cvar_RegisterVariable (&gl_fogdensity);
4005 Cvar_RegisterVariable (&gl_fogred);
4006 Cvar_RegisterVariable (&gl_foggreen);
4007 Cvar_RegisterVariable (&gl_fogblue);
4008 Cvar_RegisterVariable (&gl_fogstart);
4009 Cvar_RegisterVariable (&gl_fogend);
4010 Cvar_RegisterVariable (&gl_skyclip);
4012 Cvar_RegisterVariable(&r_motionblur);
4013 Cvar_RegisterVariable(&r_motionblur_maxblur);
4014 Cvar_RegisterVariable(&r_motionblur_bmin);
4015 Cvar_RegisterVariable(&r_motionblur_vmin);
4016 Cvar_RegisterVariable(&r_motionblur_vmax);
4017 Cvar_RegisterVariable(&r_motionblur_vcoeff);
4018 Cvar_RegisterVariable(&r_motionblur_randomize);
4019 Cvar_RegisterVariable(&r_damageblur);
4020 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4021 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4022 Cvar_RegisterVariable(&r_equalize_entities_by);
4023 Cvar_RegisterVariable(&r_equalize_entities_to);
4024 Cvar_RegisterVariable(&r_depthfirst);
4025 Cvar_RegisterVariable(&r_useinfinitefarclip);
4026 Cvar_RegisterVariable(&r_farclip_base);
4027 Cvar_RegisterVariable(&r_farclip_world);
4028 Cvar_RegisterVariable(&r_nearclip);
4029 Cvar_RegisterVariable(&r_showbboxes);
4030 Cvar_RegisterVariable(&r_showsurfaces);
4031 Cvar_RegisterVariable(&r_showtris);
4032 Cvar_RegisterVariable(&r_shownormals);
4033 Cvar_RegisterVariable(&r_showlighting);
4034 Cvar_RegisterVariable(&r_showshadowvolumes);
4035 Cvar_RegisterVariable(&r_showcollisionbrushes);
4036 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4037 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4038 Cvar_RegisterVariable(&r_showdisabledepthtest);
4039 Cvar_RegisterVariable(&r_drawportals);
4040 Cvar_RegisterVariable(&r_drawentities);
4041 Cvar_RegisterVariable(&r_draw2d);
4042 Cvar_RegisterVariable(&r_drawworld);
4043 Cvar_RegisterVariable(&r_cullentities_trace);
4044 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4045 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4046 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4047 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4048 Cvar_RegisterVariable(&r_drawviewmodel);
4049 Cvar_RegisterVariable(&r_drawexteriormodel);
4050 Cvar_RegisterVariable(&r_speeds);
4051 Cvar_RegisterVariable(&r_fullbrights);
4052 Cvar_RegisterVariable(&r_wateralpha);
4053 Cvar_RegisterVariable(&r_dynamic);
4054 Cvar_RegisterVariable(&r_fakelight);
4055 Cvar_RegisterVariable(&r_fakelight_intensity);
4056 Cvar_RegisterVariable(&r_fullbright);
4057 Cvar_RegisterVariable(&r_shadows);
4058 Cvar_RegisterVariable(&r_shadows_darken);
4059 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4060 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4061 Cvar_RegisterVariable(&r_shadows_throwdistance);
4062 Cvar_RegisterVariable(&r_shadows_throwdirection);
4063 Cvar_RegisterVariable(&r_shadows_focus);
4064 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4065 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4066 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4067 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4068 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4069 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4070 Cvar_RegisterVariable(&r_fog_exp2);
4071 Cvar_RegisterVariable(&r_fog_clear);
4072 Cvar_RegisterVariable(&r_drawfog);
4073 Cvar_RegisterVariable(&r_transparentdepthmasking);
4074 Cvar_RegisterVariable(&r_texture_dds_load);
4075 Cvar_RegisterVariable(&r_texture_dds_save);
4076 Cvar_RegisterVariable(&r_texture_sRGB_2d);
4077 Cvar_RegisterVariable(&r_texture_sRGB_skin_diffuse);
4078 Cvar_RegisterVariable(&r_texture_sRGB_skin_gloss);
4079 Cvar_RegisterVariable(&r_texture_sRGB_skin_glow);
4080 Cvar_RegisterVariable(&r_texture_sRGB_skin_reflect);
4081 Cvar_RegisterVariable(&r_texture_sRGB_cubemap);
4082 Cvar_RegisterVariable(&r_texture_sRGB_skybox);
4083 Cvar_RegisterVariable(&r_textureunits);
4084 Cvar_RegisterVariable(&gl_combine);
4085 Cvar_RegisterVariable(&r_viewfbo);
4086 Cvar_RegisterVariable(&r_viewscale);
4087 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4088 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4089 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4090 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4091 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4092 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4093 Cvar_RegisterVariable(&r_glsl);
4094 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4095 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4096 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4097 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4098 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4099 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4100 Cvar_RegisterVariable(&r_glsl_postprocess);
4101 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4102 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4103 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4104 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4105 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4106 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4107 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4108 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4110 Cvar_RegisterVariable(&r_water);
4111 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4112 Cvar_RegisterVariable(&r_water_clippingplanebias);
4113 Cvar_RegisterVariable(&r_water_refractdistort);
4114 Cvar_RegisterVariable(&r_water_reflectdistort);
4115 Cvar_RegisterVariable(&r_water_scissormode);
4116 Cvar_RegisterVariable(&r_lerpsprites);
4117 Cvar_RegisterVariable(&r_lerpmodels);
4118 Cvar_RegisterVariable(&r_lerplightstyles);
4119 Cvar_RegisterVariable(&r_waterscroll);
4120 Cvar_RegisterVariable(&r_bloom);
4121 Cvar_RegisterVariable(&r_bloom_colorscale);
4122 Cvar_RegisterVariable(&r_bloom_brighten);
4123 Cvar_RegisterVariable(&r_bloom_blur);
4124 Cvar_RegisterVariable(&r_bloom_resolution);
4125 Cvar_RegisterVariable(&r_bloom_colorexponent);
4126 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4127 Cvar_RegisterVariable(&r_hdr);
4128 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4129 Cvar_RegisterVariable(&r_hdr_glowintensity);
4130 Cvar_RegisterVariable(&r_hdr_range);
4131 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4132 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4133 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4134 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4135 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4136 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4137 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4138 Cvar_RegisterVariable(&developer_texturelogging);
4139 Cvar_RegisterVariable(&gl_lightmaps);
4140 Cvar_RegisterVariable(&r_test);
4141 Cvar_RegisterVariable(&r_glsl_saturation);
4142 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4143 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4144 Cvar_RegisterVariable(&r_framedatasize);
4145 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4146 Cvar_SetValue("r_fullbrights", 0);
4147 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4149 Cvar_RegisterVariable(&r_track_sprites);
4150 Cvar_RegisterVariable(&r_track_sprites_flags);
4151 Cvar_RegisterVariable(&r_track_sprites_scalew);
4152 Cvar_RegisterVariable(&r_track_sprites_scaleh);
4153 Cvar_RegisterVariable(&r_overheadsprites_perspective);
4154 Cvar_RegisterVariable(&r_overheadsprites_pushback);
4155 Cvar_RegisterVariable(&r_overheadsprites_scalex);
4156 Cvar_RegisterVariable(&r_overheadsprites_scaley);
4159 extern void R_Textures_Init(void);
4160 extern void GL_Draw_Init(void);
4161 extern void GL_Main_Init(void);
4162 extern void R_Shadow_Init(void);
4163 extern void R_Sky_Init(void);
4164 extern void GL_Surf_Init(void);
4165 extern void R_Particles_Init(void);
4166 extern void R_Explosion_Init(void);
4167 extern void gl_backend_init(void);
4168 extern void Sbar_Init(void);
4169 extern void R_LightningBeams_Init(void);
4170 extern void Mod_RenderInit(void);
4171 extern void Font_Init(void);
4173 void Render_Init(void)
4186 R_LightningBeams_Init();
4195 extern char *ENGINE_EXTENSIONS;
4198 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4199 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4200 gl_version = (const char *)qglGetString(GL_VERSION);
4201 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4205 if (!gl_platformextensions)
4206 gl_platformextensions = "";
4208 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4209 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4210 Con_Printf("GL_VERSION: %s\n", gl_version);
4211 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4212 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4214 VID_CheckExtensions();
4216 // LordHavoc: report supported extensions
4217 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4219 // clear to black (loading plaque will be seen over this)
4220 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4223 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4227 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4229 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4232 p = r_refdef.view.frustum + i;
4237 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4241 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4245 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4249 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4253 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4257 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4261 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4265 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4273 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4277 for (i = 0;i < numplanes;i++)
4284 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4288 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4292 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4296 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4300 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4304 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4308 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4312 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4320 //==================================================================================
4322 // LordHavoc: this stores temporary data used within the same frame
4324 typedef struct r_framedata_mem_s
4326 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4327 size_t size; // how much usable space
4328 size_t current; // how much space in use
4329 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4330 size_t wantedsize; // how much space was allocated
4331 unsigned char *data; // start of real data (16byte aligned)
4335 static r_framedata_mem_t *r_framedata_mem;
4337 void R_FrameData_Reset(void)
4339 while (r_framedata_mem)
4341 r_framedata_mem_t *next = r_framedata_mem->purge;
4342 Mem_Free(r_framedata_mem);
4343 r_framedata_mem = next;
4347 void R_FrameData_Resize(void)
4350 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4351 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4352 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4354 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4355 newmem->wantedsize = wantedsize;
4356 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4357 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4358 newmem->current = 0;
4360 newmem->purge = r_framedata_mem;
4361 r_framedata_mem = newmem;
4365 void R_FrameData_NewFrame(void)
4367 R_FrameData_Resize();
4368 if (!r_framedata_mem)
4370 // if we ran out of space on the last frame, free the old memory now
4371 while (r_framedata_mem->purge)
4373 // repeatedly remove the second item in the list, leaving only head
4374 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4375 Mem_Free(r_framedata_mem->purge);
4376 r_framedata_mem->purge = next;
4378 // reset the current mem pointer
4379 r_framedata_mem->current = 0;
4380 r_framedata_mem->mark = 0;
4383 void *R_FrameData_Alloc(size_t size)
4387 // align to 16 byte boundary - the data pointer is already aligned, so we
4388 // only need to ensure the size of every allocation is also aligned
4389 size = (size + 15) & ~15;
4391 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4393 // emergency - we ran out of space, allocate more memory
4394 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4395 R_FrameData_Resize();
4398 data = r_framedata_mem->data + r_framedata_mem->current;
4399 r_framedata_mem->current += size;
4401 // count the usage for stats
4402 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4403 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4405 return (void *)data;
4408 void *R_FrameData_Store(size_t size, void *data)
4410 void *d = R_FrameData_Alloc(size);
4412 memcpy(d, data, size);
4416 void R_FrameData_SetMark(void)
4418 if (!r_framedata_mem)
4420 r_framedata_mem->mark = r_framedata_mem->current;
4423 void R_FrameData_ReturnToMark(void)
4425 if (!r_framedata_mem)
4427 r_framedata_mem->current = r_framedata_mem->mark;
4430 //==================================================================================
4432 // LordHavoc: animcache originally written by Echon, rewritten since then
4435 * Animation cache prevents re-generating mesh data for an animated model
4436 * multiple times in one frame for lighting, shadowing, reflections, etc.
4439 void R_AnimCache_Free(void)
4443 void R_AnimCache_ClearCache(void)
4446 entity_render_t *ent;
4448 for (i = 0;i < r_refdef.scene.numentities;i++)
4450 ent = r_refdef.scene.entities[i];
4451 ent->animcache_vertex3f = NULL;
4452 ent->animcache_normal3f = NULL;
4453 ent->animcache_svector3f = NULL;
4454 ent->animcache_tvector3f = NULL;
4455 ent->animcache_vertexmesh = NULL;
4456 ent->animcache_vertex3fbuffer = NULL;
4457 ent->animcache_vertexmeshbuffer = NULL;
4461 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4465 // check if we need the meshbuffers
4466 if (!vid.useinterleavedarrays)
4469 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4470 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4471 // TODO: upload vertex3f buffer?
4472 if (ent->animcache_vertexmesh)
4474 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4475 for (i = 0;i < numvertices;i++)
4476 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4477 if (ent->animcache_svector3f)
4478 for (i = 0;i < numvertices;i++)
4479 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4480 if (ent->animcache_tvector3f)
4481 for (i = 0;i < numvertices;i++)
4482 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4483 if (ent->animcache_normal3f)
4484 for (i = 0;i < numvertices;i++)
4485 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4486 // TODO: upload vertexmeshbuffer?
4490 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4492 dp_model_t *model = ent->model;
4494 // see if it's already cached this frame
4495 if (ent->animcache_vertex3f)
4497 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4498 if (wantnormals || wanttangents)
4500 if (ent->animcache_normal3f)
4501 wantnormals = false;
4502 if (ent->animcache_svector3f)
4503 wanttangents = false;
4504 if (wantnormals || wanttangents)
4506 numvertices = model->surfmesh.num_vertices;
4508 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4511 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4512 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4514 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4515 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4521 // see if this ent is worth caching
4522 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4524 // get some memory for this entity and generate mesh data
4525 numvertices = model->surfmesh.num_vertices;
4526 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4528 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4531 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4532 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4534 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4535 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4540 void R_AnimCache_CacheVisibleEntities(void)
4543 qboolean wantnormals = true;
4544 qboolean wanttangents = !r_showsurfaces.integer;
4546 switch(vid.renderpath)
4548 case RENDERPATH_GL20:
4549 case RENDERPATH_D3D9:
4550 case RENDERPATH_D3D10:
4551 case RENDERPATH_D3D11:
4552 case RENDERPATH_GLES2:
4554 case RENDERPATH_GL13:
4555 case RENDERPATH_GL11:
4556 wanttangents = false;
4558 case RENDERPATH_SOFT:
4562 if (r_shownormals.integer)
4563 wanttangents = wantnormals = true;
4565 // TODO: thread this
4566 // NOTE: R_PrepareRTLights() also caches entities
4568 for (i = 0;i < r_refdef.scene.numentities;i++)
4569 if (r_refdef.viewcache.entityvisible[i])
4570 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4573 //==================================================================================
4575 static void R_View_UpdateEntityLighting (void)
4578 entity_render_t *ent;
4579 vec3_t tempdiffusenormal, avg;
4580 vec_t f, fa, fd, fdd;
4581 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4583 for (i = 0;i < r_refdef.scene.numentities;i++)
4585 ent = r_refdef.scene.entities[i];
4587 // skip unseen models
4588 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4592 if (ent->model && ent->model->brush.num_leafs)
4594 // TODO: use modellight for r_ambient settings on world?
4595 VectorSet(ent->modellight_ambient, 0, 0, 0);
4596 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4597 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4601 // fetch the lighting from the worldmodel data
4602 VectorClear(ent->modellight_ambient);
4603 VectorClear(ent->modellight_diffuse);
4604 VectorClear(tempdiffusenormal);
4605 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4608 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4610 // complete lightning for lit sprites
4611 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4612 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4614 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4615 org[2] = org[2] + r_overheadsprites_pushback.value;
4616 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4619 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4621 if(ent->flags & RENDER_EQUALIZE)
4623 // first fix up ambient lighting...
4624 if(r_equalize_entities_minambient.value > 0)
4626 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4629 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4630 if(fa < r_equalize_entities_minambient.value * fd)
4633 // fa'/fd' = minambient
4634 // fa'+0.25*fd' = fa+0.25*fd
4636 // fa' = fd' * minambient
4637 // fd'*(0.25+minambient) = fa+0.25*fd
4639 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4640 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4642 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4643 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
4644 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4645 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4650 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4652 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4653 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4657 // adjust brightness and saturation to target
4658 avg[0] = avg[1] = avg[2] = fa / f;
4659 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4660 avg[0] = avg[1] = avg[2] = fd / f;
4661 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4667 VectorSet(ent->modellight_ambient, 1, 1, 1);
4669 // move the light direction into modelspace coordinates for lighting code
4670 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4671 if(VectorLength2(ent->modellight_lightdir) == 0)
4672 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4673 VectorNormalize(ent->modellight_lightdir);
4677 #define MAX_LINEOFSIGHTTRACES 64
4679 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4682 vec3_t boxmins, boxmaxs;
4685 dp_model_t *model = r_refdef.scene.worldmodel;
4687 if (!model || !model->brush.TraceLineOfSight)
4690 // expand the box a little
4691 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4692 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4693 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4694 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4695 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4696 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4698 // return true if eye is inside enlarged box
4699 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4703 VectorCopy(eye, start);
4704 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4705 if (model->brush.TraceLineOfSight(model, start, end))
4708 // try various random positions
4709 for (i = 0;i < numsamples;i++)
4711 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4712 if (model->brush.TraceLineOfSight(model, start, end))
4720 static void R_View_UpdateEntityVisible (void)
4725 entity_render_t *ent;
4727 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4728 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4729 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
4730 : RENDER_EXTERIORMODEL;
4731 if (!r_drawviewmodel.integer)
4732 renderimask |= RENDER_VIEWMODEL;
4733 if (!r_drawexteriormodel.integer)
4734 renderimask |= RENDER_EXTERIORMODEL;
4735 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4737 // worldmodel can check visibility
4738 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4739 for (i = 0;i < r_refdef.scene.numentities;i++)
4741 ent = r_refdef.scene.entities[i];
4742 if (!(ent->flags & renderimask))
4743 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)))
4744 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))
4745 r_refdef.viewcache.entityvisible[i] = true;
4747 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4748 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4750 for (i = 0;i < r_refdef.scene.numentities;i++)
4752 ent = r_refdef.scene.entities[i];
4753 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4755 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4757 continue; // temp entities do pvs only
4758 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4759 ent->last_trace_visibility = realtime;
4760 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4761 r_refdef.viewcache.entityvisible[i] = 0;
4768 // no worldmodel or it can't check visibility
4769 for (i = 0;i < r_refdef.scene.numentities;i++)
4771 ent = r_refdef.scene.entities[i];
4772 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));
4777 /// only used if skyrendermasked, and normally returns false
4778 int R_DrawBrushModelsSky (void)
4781 entity_render_t *ent;
4784 for (i = 0;i < r_refdef.scene.numentities;i++)
4786 if (!r_refdef.viewcache.entityvisible[i])
4788 ent = r_refdef.scene.entities[i];
4789 if (!ent->model || !ent->model->DrawSky)
4791 ent->model->DrawSky(ent);
4797 static void R_DrawNoModel(entity_render_t *ent);
4798 static void R_DrawModels(void)
4801 entity_render_t *ent;
4803 for (i = 0;i < r_refdef.scene.numentities;i++)
4805 if (!r_refdef.viewcache.entityvisible[i])
4807 ent = r_refdef.scene.entities[i];
4808 r_refdef.stats.entities++;
4809 if (ent->model && ent->model->Draw != NULL)
4810 ent->model->Draw(ent);
4816 static void R_DrawModelsDepth(void)
4819 entity_render_t *ent;
4821 for (i = 0;i < r_refdef.scene.numentities;i++)
4823 if (!r_refdef.viewcache.entityvisible[i])
4825 ent = r_refdef.scene.entities[i];
4826 if (ent->model && ent->model->DrawDepth != NULL)
4827 ent->model->DrawDepth(ent);
4831 static void R_DrawModelsDebug(void)
4834 entity_render_t *ent;
4836 for (i = 0;i < r_refdef.scene.numentities;i++)
4838 if (!r_refdef.viewcache.entityvisible[i])
4840 ent = r_refdef.scene.entities[i];
4841 if (ent->model && ent->model->DrawDebug != NULL)
4842 ent->model->DrawDebug(ent);
4846 static void R_DrawModelsAddWaterPlanes(void)
4849 entity_render_t *ent;
4851 for (i = 0;i < r_refdef.scene.numentities;i++)
4853 if (!r_refdef.viewcache.entityvisible[i])
4855 ent = r_refdef.scene.entities[i];
4856 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4857 ent->model->DrawAddWaterPlanes(ent);
4861 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4863 if (r_hdr_irisadaptation.integer)
4867 vec3_t diffusenormal;
4872 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4873 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4874 brightness = max(0.0000001f, brightness);
4875 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4876 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4877 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4878 current = r_hdr_irisadaptation_value.value;
4880 current = min(current + adjust, goal);
4881 else if (current > goal)
4882 current = max(current - adjust, goal);
4883 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4884 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4886 else if (r_hdr_irisadaptation_value.value != 1.0f)
4887 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4890 static void R_View_SetFrustum(const int *scissor)
4893 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4894 vec3_t forward, left, up, origin, v;
4898 // flipped x coordinates (because x points left here)
4899 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4900 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4902 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4903 switch(vid.renderpath)
4905 case RENDERPATH_D3D9:
4906 case RENDERPATH_D3D10:
4907 case RENDERPATH_D3D11:
4908 // non-flipped y coordinates
4909 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4910 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4912 case RENDERPATH_SOFT:
4913 case RENDERPATH_GL11:
4914 case RENDERPATH_GL13:
4915 case RENDERPATH_GL20:
4916 case RENDERPATH_GLES2:
4917 // non-flipped y coordinates
4918 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4919 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4924 // we can't trust r_refdef.view.forward and friends in reflected scenes
4925 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4928 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4929 r_refdef.view.frustum[0].normal[1] = 0 - 0;
4930 r_refdef.view.frustum[0].normal[2] = -1 - 0;
4931 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4932 r_refdef.view.frustum[1].normal[1] = 0 + 0;
4933 r_refdef.view.frustum[1].normal[2] = -1 + 0;
4934 r_refdef.view.frustum[2].normal[0] = 0 - 0;
4935 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4936 r_refdef.view.frustum[2].normal[2] = -1 - 0;
4937 r_refdef.view.frustum[3].normal[0] = 0 + 0;
4938 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4939 r_refdef.view.frustum[3].normal[2] = -1 + 0;
4943 zNear = r_refdef.nearclip;
4944 nudge = 1.0 - 1.0 / (1<<23);
4945 r_refdef.view.frustum[4].normal[0] = 0 - 0;
4946 r_refdef.view.frustum[4].normal[1] = 0 - 0;
4947 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4948 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4949 r_refdef.view.frustum[5].normal[0] = 0 + 0;
4950 r_refdef.view.frustum[5].normal[1] = 0 + 0;
4951 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4952 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4958 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4959 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4960 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4961 r_refdef.view.frustum[0].dist = m[15] - m[12];
4963 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4964 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4965 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4966 r_refdef.view.frustum[1].dist = m[15] + m[12];
4968 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4969 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4970 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4971 r_refdef.view.frustum[2].dist = m[15] - m[13];
4973 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4974 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4975 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4976 r_refdef.view.frustum[3].dist = m[15] + m[13];
4978 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4979 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4980 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4981 r_refdef.view.frustum[4].dist = m[15] - m[14];
4983 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
4984 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
4985 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
4986 r_refdef.view.frustum[5].dist = m[15] + m[14];
4989 if (r_refdef.view.useperspective)
4991 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
4992 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]);
4993 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]);
4994 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]);
4995 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]);
4997 // then the normals from the corners relative to origin
4998 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
4999 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5000 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5001 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5003 // in a NORMAL view, forward cross left == up
5004 // in a REFLECTED view, forward cross left == down
5005 // so our cross products above need to be adjusted for a left handed coordinate system
5006 CrossProduct(forward, left, v);
5007 if(DotProduct(v, up) < 0)
5009 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5010 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5011 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5012 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5015 // Leaving those out was a mistake, those were in the old code, and they
5016 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5017 // I couldn't reproduce it after adding those normalizations. --blub
5018 VectorNormalize(r_refdef.view.frustum[0].normal);
5019 VectorNormalize(r_refdef.view.frustum[1].normal);
5020 VectorNormalize(r_refdef.view.frustum[2].normal);
5021 VectorNormalize(r_refdef.view.frustum[3].normal);
5023 // make the corners absolute
5024 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5025 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5026 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5027 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5030 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5032 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5033 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5034 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5035 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5036 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5040 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5041 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5042 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5043 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5044 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5045 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5046 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5047 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5048 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5049 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5051 r_refdef.view.numfrustumplanes = 5;
5053 if (r_refdef.view.useclipplane)
5055 r_refdef.view.numfrustumplanes = 6;
5056 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5059 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5060 PlaneClassify(r_refdef.view.frustum + i);
5062 // LordHavoc: note to all quake engine coders, Quake had a special case
5063 // for 90 degrees which assumed a square view (wrong), so I removed it,
5064 // Quake2 has it disabled as well.
5066 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5067 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5068 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5069 //PlaneClassify(&frustum[0]);
5071 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5072 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5073 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5074 //PlaneClassify(&frustum[1]);
5076 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5077 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5078 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5079 //PlaneClassify(&frustum[2]);
5081 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5082 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5083 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5084 //PlaneClassify(&frustum[3]);
5087 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5088 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5089 //PlaneClassify(&frustum[4]);
5092 void R_View_UpdateWithScissor(const int *myscissor)
5094 R_Main_ResizeViewCache();
5095 R_View_SetFrustum(myscissor);
5096 R_View_WorldVisibility(r_refdef.view.useclipplane);
5097 R_View_UpdateEntityVisible();
5098 R_View_UpdateEntityLighting();
5101 void R_View_Update(void)
5103 R_Main_ResizeViewCache();
5104 R_View_SetFrustum(NULL);
5105 R_View_WorldVisibility(r_refdef.view.useclipplane);
5106 R_View_UpdateEntityVisible();
5107 R_View_UpdateEntityLighting();
5110 float viewscalefpsadjusted = 1.0f;
5112 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5114 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5115 scale = bound(0.03125f, scale, 1.0f);
5116 *outwidth = (int)ceil(width * scale);
5117 *outheight = (int)ceil(height * scale);
5120 void R_Mesh_SetMainRenderTargets(void)
5122 if (r_bloomstate.fbo_framebuffer)
5123 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5125 R_Mesh_ResetRenderTargets();
5128 void R_SetupView(qboolean allowwaterclippingplane)
5130 const float *customclipplane = NULL;
5132 int scaledwidth, scaledheight;
5133 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5135 // LordHavoc: couldn't figure out how to make this approach the
5136 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5137 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5138 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5139 dist = r_refdef.view.clipplane.dist;
5140 plane[0] = r_refdef.view.clipplane.normal[0];
5141 plane[1] = r_refdef.view.clipplane.normal[1];
5142 plane[2] = r_refdef.view.clipplane.normal[2];
5144 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5147 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5148 if (!r_refdef.view.useperspective)
5149 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, -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);
5150 else if (vid.stencil && r_useinfinitefarclip.integer)
5151 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
5153 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
5154 R_Mesh_SetMainRenderTargets();
5155 R_SetViewport(&r_refdef.view.viewport);
5156 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5158 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5159 float screenplane[4];
5160 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5161 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5162 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5163 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5164 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5168 void R_EntityMatrix(const matrix4x4_t *matrix)
5170 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5172 gl_modelmatrixchanged = false;
5173 gl_modelmatrix = *matrix;
5174 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5175 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5176 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5177 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5179 switch(vid.renderpath)
5181 case RENDERPATH_D3D9:
5183 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5184 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5187 case RENDERPATH_D3D10:
5188 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5190 case RENDERPATH_D3D11:
5191 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5193 case RENDERPATH_GL13:
5194 case RENDERPATH_GL11:
5195 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5197 case RENDERPATH_SOFT:
5198 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5199 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5201 case RENDERPATH_GL20:
5202 case RENDERPATH_GLES2:
5203 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5204 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5210 void R_ResetViewRendering2D(void)
5212 r_viewport_t viewport;
5215 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5216 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);
5217 R_Mesh_ResetRenderTargets();
5218 R_SetViewport(&viewport);
5219 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5220 GL_Color(1, 1, 1, 1);
5221 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5222 GL_BlendFunc(GL_ONE, GL_ZERO);
5223 GL_ScissorTest(false);
5224 GL_DepthMask(false);
5225 GL_DepthRange(0, 1);
5226 GL_DepthTest(false);
5227 GL_DepthFunc(GL_LEQUAL);
5228 R_EntityMatrix(&identitymatrix);
5229 R_Mesh_ResetTextureState();
5230 GL_PolygonOffset(0, 0);
5231 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5232 switch(vid.renderpath)
5234 case RENDERPATH_GL11:
5235 case RENDERPATH_GL13:
5236 case RENDERPATH_GL20:
5237 case RENDERPATH_GLES2:
5238 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5240 case RENDERPATH_D3D9:
5241 case RENDERPATH_D3D10:
5242 case RENDERPATH_D3D11:
5243 case RENDERPATH_SOFT:
5246 GL_CullFace(GL_NONE);
5249 void R_ResetViewRendering3D(void)
5254 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5255 GL_Color(1, 1, 1, 1);
5256 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5257 GL_BlendFunc(GL_ONE, GL_ZERO);
5258 GL_ScissorTest(true);
5260 GL_DepthRange(0, 1);
5262 GL_DepthFunc(GL_LEQUAL);
5263 R_EntityMatrix(&identitymatrix);
5264 R_Mesh_ResetTextureState();
5265 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5266 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5267 switch(vid.renderpath)
5269 case RENDERPATH_GL11:
5270 case RENDERPATH_GL13:
5271 case RENDERPATH_GL20:
5272 case RENDERPATH_GLES2:
5273 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5275 case RENDERPATH_D3D9:
5276 case RENDERPATH_D3D10:
5277 case RENDERPATH_D3D11:
5278 case RENDERPATH_SOFT:
5281 GL_CullFace(r_refdef.view.cullface_back);
5286 R_RenderView_UpdateViewVectors
5289 static void R_RenderView_UpdateViewVectors(void)
5291 // break apart the view matrix into vectors for various purposes
5292 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5293 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5294 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5295 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5296 // make an inverted copy of the view matrix for tracking sprites
5297 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5300 void R_RenderScene(void);
5301 void R_RenderWaterPlanes(void);
5303 static void R_Water_StartFrame(void)
5306 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5307 r_waterstate_waterplane_t *p;
5309 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5312 switch(vid.renderpath)
5314 case RENDERPATH_GL20:
5315 case RENDERPATH_D3D9:
5316 case RENDERPATH_D3D10:
5317 case RENDERPATH_D3D11:
5318 case RENDERPATH_SOFT:
5319 case RENDERPATH_GLES2:
5321 case RENDERPATH_GL13:
5322 case RENDERPATH_GL11:
5326 // set waterwidth and waterheight to the water resolution that will be
5327 // used (often less than the screen resolution for faster rendering)
5328 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5329 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5331 // calculate desired texture sizes
5332 // can't use water if the card does not support the texture size
5333 if (!r_water.integer || r_showsurfaces.integer)
5334 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5335 else if (vid.support.arb_texture_non_power_of_two)
5337 texturewidth = waterwidth;
5338 textureheight = waterheight;
5339 camerawidth = waterwidth;
5340 cameraheight = waterheight;
5344 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5345 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5346 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5347 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5350 // allocate textures as needed
5351 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5353 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5354 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5356 if (p->texture_refraction)
5357 R_FreeTexture(p->texture_refraction);
5358 p->texture_refraction = NULL;
5359 if (p->texture_reflection)
5360 R_FreeTexture(p->texture_reflection);
5361 p->texture_reflection = NULL;
5362 if (p->texture_camera)
5363 R_FreeTexture(p->texture_camera);
5364 p->texture_camera = NULL;
5366 memset(&r_waterstate, 0, sizeof(r_waterstate));
5367 r_waterstate.texturewidth = texturewidth;
5368 r_waterstate.textureheight = textureheight;
5369 r_waterstate.camerawidth = camerawidth;
5370 r_waterstate.cameraheight = cameraheight;
5373 if (r_waterstate.texturewidth)
5375 r_waterstate.enabled = true;
5377 // when doing a reduced render (HDR) we want to use a smaller area
5378 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5379 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5381 // set up variables that will be used in shader setup
5382 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5383 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5384 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5385 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5388 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5389 r_waterstate.numwaterplanes = 0;
5392 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5394 int triangleindex, planeindex;
5400 r_waterstate_waterplane_t *p;
5401 texture_t *t = R_GetCurrentTexture(surface->texture);
5403 // just use the first triangle with a valid normal for any decisions
5404 VectorClear(normal);
5405 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5407 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5408 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5409 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5410 TriangleNormal(vert[0], vert[1], vert[2], normal);
5411 if (VectorLength2(normal) >= 0.001)
5415 VectorCopy(normal, plane.normal);
5416 VectorNormalize(plane.normal);
5417 plane.dist = DotProduct(vert[0], plane.normal);
5418 PlaneClassify(&plane);
5419 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5421 // skip backfaces (except if nocullface is set)
5422 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5424 VectorNegate(plane.normal, plane.normal);
5426 PlaneClassify(&plane);
5430 // find a matching plane if there is one
5431 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5432 if(p->camera_entity == t->camera_entity)
5433 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5435 if (planeindex >= r_waterstate.maxwaterplanes)
5436 return; // nothing we can do, out of planes
5438 // if this triangle does not fit any known plane rendered this frame, add one
5439 if (planeindex >= r_waterstate.numwaterplanes)
5441 // store the new plane
5442 r_waterstate.numwaterplanes++;
5444 // clear materialflags and pvs
5445 p->materialflags = 0;
5446 p->pvsvalid = false;
5447 p->camera_entity = t->camera_entity;
5448 VectorCopy(surface->mins, p->mins);
5449 VectorCopy(surface->maxs, p->maxs);
5454 p->mins[0] = min(p->mins[0], surface->mins[0]);
5455 p->mins[1] = min(p->mins[1], surface->mins[1]);
5456 p->mins[2] = min(p->mins[2], surface->mins[2]);
5457 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5458 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5459 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5461 // merge this surface's materialflags into the waterplane
5462 p->materialflags |= t->currentmaterialflags;
5463 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5465 // merge this surface's PVS into the waterplane
5466 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5467 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5468 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5470 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5476 static void R_Water_ProcessPlanes(void)
5479 r_refdef_view_t originalview;
5480 r_refdef_view_t myview;
5482 r_waterstate_waterplane_t *p;
5485 originalview = r_refdef.view;
5487 // make sure enough textures are allocated
5488 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5490 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5492 if (!p->texture_refraction)
5493 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);
5494 if (!p->texture_refraction)
5497 else if (p->materialflags & MATERIALFLAG_CAMERA)
5499 if (!p->texture_camera)
5500 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);
5501 if (!p->texture_camera)
5505 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5507 if (!p->texture_reflection)
5508 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);
5509 if (!p->texture_reflection)
5515 r_refdef.view = originalview;
5516 r_refdef.view.showdebug = false;
5517 r_refdef.view.width = r_waterstate.waterwidth;
5518 r_refdef.view.height = r_waterstate.waterheight;
5519 r_refdef.view.useclipplane = true;
5520 myview = r_refdef.view;
5521 r_waterstate.renderingscene = true;
5522 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5524 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5526 r_refdef.view = myview;
5527 if(r_water_scissormode.integer)
5530 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5531 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5534 // render reflected scene and copy into texture
5535 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5536 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5537 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5538 r_refdef.view.clipplane = p->plane;
5540 // reverse the cullface settings for this render
5541 r_refdef.view.cullface_front = GL_FRONT;
5542 r_refdef.view.cullface_back = GL_BACK;
5543 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5545 r_refdef.view.usecustompvs = true;
5547 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5549 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5552 R_ResetViewRendering3D();
5553 R_ClearScreen(r_refdef.fogenabled);
5554 if(r_water_scissormode.integer & 2)
5555 R_View_UpdateWithScissor(myscissor);
5558 if(r_water_scissormode.integer & 1)
5559 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5562 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);
5565 // render the normal view scene and copy into texture
5566 // (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)
5567 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5569 r_refdef.view = myview;
5570 if(r_water_scissormode.integer)
5573 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5574 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5577 r_waterstate.renderingrefraction = true;
5579 r_refdef.view.clipplane = p->plane;
5580 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5581 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5583 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5585 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5586 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5587 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5588 R_RenderView_UpdateViewVectors();
5589 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5591 r_refdef.view.usecustompvs = true;
5592 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);
5596 PlaneClassify(&r_refdef.view.clipplane);
5598 R_ResetViewRendering3D();
5599 R_ClearScreen(r_refdef.fogenabled);
5600 if(r_water_scissormode.integer & 2)
5601 R_View_UpdateWithScissor(myscissor);
5604 if(r_water_scissormode.integer & 1)
5605 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5608 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);
5609 r_waterstate.renderingrefraction = false;
5611 else if (p->materialflags & MATERIALFLAG_CAMERA)
5613 r_refdef.view = myview;
5615 r_refdef.view.clipplane = p->plane;
5616 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5617 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5619 r_refdef.view.width = r_waterstate.camerawidth;
5620 r_refdef.view.height = r_waterstate.cameraheight;
5621 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5622 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5624 if(p->camera_entity)
5626 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5627 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5630 // note: all of the view is used for displaying... so
5631 // there is no use in scissoring
5633 // reverse the cullface settings for this render
5634 r_refdef.view.cullface_front = GL_FRONT;
5635 r_refdef.view.cullface_back = GL_BACK;
5636 // also reverse the view matrix
5637 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
5638 R_RenderView_UpdateViewVectors();
5639 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5641 r_refdef.view.usecustompvs = true;
5642 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);
5645 // camera needs no clipplane
5646 r_refdef.view.useclipplane = false;
5648 PlaneClassify(&r_refdef.view.clipplane);
5650 R_ResetViewRendering3D();
5651 R_ClearScreen(r_refdef.fogenabled);
5655 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);
5656 r_waterstate.renderingrefraction = false;
5660 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5661 r_waterstate.renderingscene = false;
5662 r_refdef.view = originalview;
5663 R_ResetViewRendering3D();
5664 R_ClearScreen(r_refdef.fogenabled);
5668 r_refdef.view = originalview;
5669 r_waterstate.renderingscene = false;
5670 Cvar_SetValueQuick(&r_water, 0);
5671 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5675 void R_Bloom_StartFrame(void)
5677 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5678 int viewwidth, viewheight;
5681 if (r_viewscale_fpsscaling.integer)
5683 double actualframetime;
5684 double targetframetime;
5686 actualframetime = r_refdef.lastdrawscreentime;
5687 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5688 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5689 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5690 if (r_viewscale_fpsscaling_stepsize.value > 0)
5691 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5692 viewscalefpsadjusted += adjust;
5693 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5696 viewscalefpsadjusted = 1.0f;
5698 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5700 switch(vid.renderpath)
5702 case RENDERPATH_GL20:
5703 case RENDERPATH_D3D9:
5704 case RENDERPATH_D3D10:
5705 case RENDERPATH_D3D11:
5706 case RENDERPATH_SOFT:
5707 case RENDERPATH_GLES2:
5709 case RENDERPATH_GL13:
5710 case RENDERPATH_GL11:
5714 // set bloomwidth and bloomheight to the bloom resolution that will be
5715 // used (often less than the screen resolution for faster rendering)
5716 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5717 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5718 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5719 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5720 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5722 // calculate desired texture sizes
5723 if (vid.support.arb_texture_non_power_of_two)
5725 screentexturewidth = vid.width;
5726 screentextureheight = vid.height;
5727 bloomtexturewidth = r_bloomstate.bloomwidth;
5728 bloomtextureheight = r_bloomstate.bloomheight;
5732 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
5733 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
5734 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
5735 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
5738 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))
5740 Cvar_SetValueQuick(&r_hdr, 0);
5741 Cvar_SetValueQuick(&r_bloom, 0);
5742 Cvar_SetValueQuick(&r_motionblur, 0);
5743 Cvar_SetValueQuick(&r_damageblur, 0);
5746 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)) && r_viewfbo.integer < 1 && r_viewscale.value == 1.0f && !r_viewscale_fpsscaling.integer)
5747 screentexturewidth = screentextureheight = 0;
5748 if (!r_hdr.integer && !r_bloom.integer)
5749 bloomtexturewidth = bloomtextureheight = 0;
5751 textype = TEXTYPE_COLORBUFFER;
5752 switch (vid.renderpath)
5754 case RENDERPATH_GL20:
5755 case RENDERPATH_GLES2:
5756 if (vid.support.ext_framebuffer_object)
5758 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5759 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5762 case RENDERPATH_D3D9:
5763 case RENDERPATH_D3D10:
5764 case RENDERPATH_D3D11:
5765 case RENDERPATH_SOFT:
5766 case RENDERPATH_GL13:
5767 case RENDERPATH_GL11:
5771 // allocate textures as needed
5772 if (r_bloomstate.screentexturewidth != screentexturewidth
5773 || r_bloomstate.screentextureheight != screentextureheight
5774 || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5775 || r_bloomstate.bloomtextureheight != bloomtextureheight
5776 || r_bloomstate.texturetype != textype
5777 || r_bloomstate.viewfbo != r_viewfbo.integer)
5779 if (r_bloomstate.texture_bloom)
5780 R_FreeTexture(r_bloomstate.texture_bloom);
5781 r_bloomstate.texture_bloom = NULL;
5782 if (r_bloomstate.texture_screen)
5783 R_FreeTexture(r_bloomstate.texture_screen);
5784 r_bloomstate.texture_screen = NULL;
5785 if (r_bloomstate.fbo_framebuffer)
5786 R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5787 r_bloomstate.fbo_framebuffer = 0;
5788 if (r_bloomstate.texture_framebuffercolor)
5789 R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5790 r_bloomstate.texture_framebuffercolor = NULL;
5791 if (r_bloomstate.texture_framebufferdepth)
5792 R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5793 r_bloomstate.texture_framebufferdepth = NULL;
5794 r_bloomstate.screentexturewidth = screentexturewidth;
5795 r_bloomstate.screentextureheight = screentextureheight;
5796 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5797 r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5798 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5800 // FIXME: choose depth bits based on a cvar
5801 r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5802 r_bloomstate.texture_framebuffercolor = R_LoadTexture2D(r_main_texturepool, "framebuffercolor", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5803 r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5804 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5805 // render depth into one texture and normalmap into the other
5809 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5810 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5811 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
5812 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
5813 Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
5816 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5817 r_bloomstate.bloomtextureheight = bloomtextureheight;
5818 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5819 r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5820 r_bloomstate.viewfbo = r_viewfbo.integer;
5821 r_bloomstate.texturetype = textype;
5824 // when doing a reduced render (HDR) we want to use a smaller area
5825 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5826 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5827 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5828 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5829 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5831 // set up a texcoord array for the full resolution screen image
5832 // (we have to keep this around to copy back during final render)
5833 r_bloomstate.screentexcoord2f[0] = 0;
5834 r_bloomstate.screentexcoord2f[1] = (float)viewheight / (float)r_bloomstate.screentextureheight;
5835 r_bloomstate.screentexcoord2f[2] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
5836 r_bloomstate.screentexcoord2f[3] = (float)viewheight / (float)r_bloomstate.screentextureheight;
5837 r_bloomstate.screentexcoord2f[4] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
5838 r_bloomstate.screentexcoord2f[5] = 0;
5839 r_bloomstate.screentexcoord2f[6] = 0;
5840 r_bloomstate.screentexcoord2f[7] = 0;
5842 // set up a texcoord array for the reduced resolution bloom image
5843 // (which will be additive blended over the screen image)
5844 r_bloomstate.bloomtexcoord2f[0] = 0;
5845 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5846 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5847 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5848 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5849 r_bloomstate.bloomtexcoord2f[5] = 0;
5850 r_bloomstate.bloomtexcoord2f[6] = 0;
5851 r_bloomstate.bloomtexcoord2f[7] = 0;
5853 switch(vid.renderpath)
5855 case RENDERPATH_GL11:
5856 case RENDERPATH_GL13:
5857 case RENDERPATH_GL20:
5858 case RENDERPATH_SOFT:
5859 case RENDERPATH_GLES2:
5861 case RENDERPATH_D3D9:
5862 case RENDERPATH_D3D10:
5863 case RENDERPATH_D3D11:
5866 for (i = 0;i < 4;i++)
5868 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5869 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5870 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5871 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5877 if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
5879 r_bloomstate.enabled = true;
5880 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
5883 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);
5885 if (r_bloomstate.fbo_framebuffer)
5886 r_refdef.view.clear = true;
5889 void R_Bloom_CopyBloomTexture(float colorscale)
5891 r_refdef.stats.bloom++;
5893 // scale down screen texture to the bloom texture size
5895 R_Mesh_SetMainRenderTargets();
5896 R_SetViewport(&r_bloomstate.viewport);
5897 GL_BlendFunc(GL_ONE, GL_ZERO);
5898 GL_Color(colorscale, colorscale, colorscale, 1);
5899 // D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that...
5900 switch(vid.renderpath)
5902 case RENDERPATH_GL11:
5903 case RENDERPATH_GL13:
5904 case RENDERPATH_GL20:
5905 case RENDERPATH_SOFT:
5906 case RENDERPATH_GLES2:
5907 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5909 case RENDERPATH_D3D9:
5910 case RENDERPATH_D3D10:
5911 case RENDERPATH_D3D11:
5912 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5915 // TODO: do boxfilter scale-down in shader?
5916 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5917 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5918 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5920 // we now have a bloom image in the framebuffer
5921 // copy it into the bloom image texture for later processing
5922 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
5923 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5926 void R_Bloom_CopyHDRTexture(void)
5928 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5929 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5932 void R_Bloom_MakeTexture(void)
5935 float xoffset, yoffset, r, brighten;
5937 r_refdef.stats.bloom++;
5939 R_ResetViewRendering2D();
5941 // we have a bloom image in the framebuffer
5943 R_SetViewport(&r_bloomstate.viewport);
5945 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5948 r = bound(0, r_bloom_colorexponent.value / x, 1);
5949 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5951 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5952 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5953 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5954 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5956 // copy the vertically blurred bloom view to a texture
5957 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
5958 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5961 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5962 brighten = r_bloom_brighten.value;
5963 if (r_bloomstate.hdr)
5964 brighten *= r_hdr_range.value;
5965 brighten = sqrt(brighten);
5967 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5968 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5970 for (dir = 0;dir < 2;dir++)
5972 // blend on at multiple vertical offsets to achieve a vertical blur
5973 // TODO: do offset blends using GLSL
5974 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5975 GL_BlendFunc(GL_ONE, GL_ZERO);
5976 for (x = -range;x <= range;x++)
5978 if (!dir){xoffset = 0;yoffset = x;}
5979 else {xoffset = x;yoffset = 0;}
5980 xoffset /= (float)r_bloomstate.bloomtexturewidth;
5981 yoffset /= (float)r_bloomstate.bloomtextureheight;
5982 // compute a texcoord array with the specified x and y offset
5983 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
5984 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5985 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5986 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5987 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5988 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
5989 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
5990 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
5991 // this r value looks like a 'dot' particle, fading sharply to
5992 // black at the edges
5993 // (probably not realistic but looks good enough)
5994 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
5995 //r = brighten/(range*2+1);
5996 r = brighten / (range * 2 + 1);
5998 r *= (1 - x*x/(float)(range*range));
5999 GL_Color(r, r, r, 1);
6000 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6001 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6002 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6003 GL_BlendFunc(GL_ONE, GL_ONE);
6006 // copy the vertically blurred bloom view to a texture
6007 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
6008 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6012 void R_HDR_RenderBloomTexture(void)
6014 int oldwidth, oldheight;
6015 float oldcolorscale;
6016 qboolean oldwaterstate;
6018 oldwaterstate = r_waterstate.enabled;
6019 oldcolorscale = r_refdef.view.colorscale;
6020 oldwidth = r_refdef.view.width;
6021 oldheight = r_refdef.view.height;
6022 r_refdef.view.width = r_bloomstate.bloomwidth;
6023 r_refdef.view.height = r_bloomstate.bloomheight;
6025 if(r_hdr.integer < 2)
6026 r_waterstate.enabled = false;
6028 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
6029 // TODO: add exposure compensation features
6030 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6032 r_refdef.view.showdebug = false;
6033 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6035 R_ResetViewRendering3D();
6037 R_ClearScreen(r_refdef.fogenabled);
6038 if (r_timereport_active)
6039 R_TimeReport("HDRclear");
6042 if (r_timereport_active)
6043 R_TimeReport("visibility");
6045 // only do secondary renders with HDR if r_hdr is 2 or higher
6046 r_waterstate.numwaterplanes = 0;
6047 if (r_waterstate.enabled)
6048 R_RenderWaterPlanes();
6050 r_refdef.view.showdebug = true;
6052 r_waterstate.numwaterplanes = 0;
6054 R_ResetViewRendering2D();
6056 R_Bloom_CopyHDRTexture();
6057 R_Bloom_MakeTexture();
6059 // restore the view settings
6060 r_waterstate.enabled = oldwaterstate;
6061 r_refdef.view.width = oldwidth;
6062 r_refdef.view.height = oldheight;
6063 r_refdef.view.colorscale = oldcolorscale;
6065 R_ResetViewRendering3D();
6067 R_ClearScreen(r_refdef.fogenabled);
6068 if (r_timereport_active)
6069 R_TimeReport("viewclear");
6072 static void R_BlendView(void)
6074 unsigned int permutation;
6075 float uservecs[4][4];
6077 switch (vid.renderpath)
6079 case RENDERPATH_GL20:
6080 case RENDERPATH_D3D9:
6081 case RENDERPATH_D3D10:
6082 case RENDERPATH_D3D11:
6083 case RENDERPATH_SOFT:
6084 case RENDERPATH_GLES2:
6086 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6087 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6088 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6089 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6090 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6092 if (r_bloomstate.texture_screen)
6094 // make sure the buffer is available
6095 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6097 R_ResetViewRendering2D();
6098 R_Mesh_SetMainRenderTargets();
6100 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6102 // declare variables
6104 static float avgspeed;
6106 speed = VectorLength(cl.movement_velocity);
6108 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6109 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6111 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6112 speed = bound(0, speed, 1);
6113 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6115 // calculate values into a standard alpha
6116 cl.motionbluralpha = 1 - exp(-
6118 (r_motionblur.value * speed / 80)
6120 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6123 max(0.0001, cl.time - cl.oldtime) // fps independent
6126 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6127 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6129 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6131 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6132 GL_Color(1, 1, 1, cl.motionbluralpha);
6133 switch(vid.renderpath)
6135 case RENDERPATH_GL11:
6136 case RENDERPATH_GL13:
6137 case RENDERPATH_GL20:
6138 case RENDERPATH_SOFT:
6139 case RENDERPATH_GLES2:
6140 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6142 case RENDERPATH_D3D9:
6143 case RENDERPATH_D3D10:
6144 case RENDERPATH_D3D11:
6145 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6148 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6149 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6150 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6154 // copy view into the screen texture
6155 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);
6156 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6158 else if (!r_bloomstate.texture_bloom)
6160 // we may still have to do view tint...
6161 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6163 // apply a color tint to the whole view
6164 R_ResetViewRendering2D();
6165 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6166 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6167 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6168 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6169 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6171 break; // no screen processing, no bloom, skip it
6174 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6176 // render simple bloom effect
6177 // copy the screen and shrink it and darken it for the bloom process
6178 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6179 // make the bloom texture
6180 R_Bloom_MakeTexture();
6183 #if _MSC_VER >= 1400
6184 #define sscanf sscanf_s
6186 memset(uservecs, 0, sizeof(uservecs));
6187 if (r_glsl_postprocess_uservec1_enable.integer)
6188 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6189 if (r_glsl_postprocess_uservec2_enable.integer)
6190 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6191 if (r_glsl_postprocess_uservec3_enable.integer)
6192 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6193 if (r_glsl_postprocess_uservec4_enable.integer)
6194 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6196 R_ResetViewRendering2D();
6197 GL_Color(1, 1, 1, 1);
6198 GL_BlendFunc(GL_ONE, GL_ZERO);
6200 switch(vid.renderpath)
6202 case RENDERPATH_GL20:
6203 case RENDERPATH_GLES2:
6204 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6205 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6206 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6207 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6208 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6209 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]);
6210 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6211 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]);
6212 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]);
6213 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]);
6214 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]);
6215 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6216 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6217 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);
6219 case RENDERPATH_D3D9:
6221 // 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...
6222 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6223 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6224 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6225 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6226 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6227 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6228 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6229 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6230 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6231 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6232 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6233 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6234 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6235 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6238 case RENDERPATH_D3D10:
6239 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6241 case RENDERPATH_D3D11:
6242 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6244 case RENDERPATH_SOFT:
6245 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6246 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6247 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6248 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6249 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6250 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6251 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6252 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6253 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6254 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6255 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6256 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6257 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6258 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6263 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6264 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6266 case RENDERPATH_GL13:
6267 case RENDERPATH_GL11:
6268 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6270 // apply a color tint to the whole view
6271 R_ResetViewRendering2D();
6272 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6273 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6274 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6275 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6276 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6282 matrix4x4_t r_waterscrollmatrix;
6284 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6286 if (r_refdef.fog_density)
6288 r_refdef.fogcolor[0] = r_refdef.fog_red;
6289 r_refdef.fogcolor[1] = r_refdef.fog_green;
6290 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6292 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6293 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6294 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6295 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6299 VectorCopy(r_refdef.fogcolor, fogvec);
6300 // color.rgb *= ContrastBoost * SceneBrightness;
6301 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6302 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6303 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6304 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6309 void R_UpdateVariables(void)
6313 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6315 r_refdef.farclip = r_farclip_base.value;
6316 if (r_refdef.scene.worldmodel)
6317 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6318 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6320 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6321 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6322 r_refdef.polygonfactor = 0;
6323 r_refdef.polygonoffset = 0;
6324 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6325 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6327 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6328 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6329 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6330 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6331 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6332 if (FAKELIGHT_ENABLED)
6334 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6336 if (r_showsurfaces.integer)
6338 r_refdef.scene.rtworld = false;
6339 r_refdef.scene.rtworldshadows = false;
6340 r_refdef.scene.rtdlight = false;
6341 r_refdef.scene.rtdlightshadows = false;
6342 r_refdef.lightmapintensity = 0;
6345 if (gamemode == GAME_NEHAHRA)
6347 if (gl_fogenable.integer)
6349 r_refdef.oldgl_fogenable = true;
6350 r_refdef.fog_density = gl_fogdensity.value;
6351 r_refdef.fog_red = gl_fogred.value;
6352 r_refdef.fog_green = gl_foggreen.value;
6353 r_refdef.fog_blue = gl_fogblue.value;
6354 r_refdef.fog_alpha = 1;
6355 r_refdef.fog_start = 0;
6356 r_refdef.fog_end = gl_skyclip.value;
6357 r_refdef.fog_height = 1<<30;
6358 r_refdef.fog_fadedepth = 128;
6360 else if (r_refdef.oldgl_fogenable)
6362 r_refdef.oldgl_fogenable = false;
6363 r_refdef.fog_density = 0;
6364 r_refdef.fog_red = 0;
6365 r_refdef.fog_green = 0;
6366 r_refdef.fog_blue = 0;
6367 r_refdef.fog_alpha = 0;
6368 r_refdef.fog_start = 0;
6369 r_refdef.fog_end = 0;
6370 r_refdef.fog_height = 1<<30;
6371 r_refdef.fog_fadedepth = 128;
6375 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6376 r_refdef.fog_start = max(0, r_refdef.fog_start);
6377 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6379 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6381 if (r_refdef.fog_density && r_drawfog.integer)
6383 r_refdef.fogenabled = true;
6384 // this is the point where the fog reaches 0.9986 alpha, which we
6385 // consider a good enough cutoff point for the texture
6386 // (0.9986 * 256 == 255.6)
6387 if (r_fog_exp2.integer)
6388 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6390 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6391 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6392 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6393 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6394 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6395 R_BuildFogHeightTexture();
6396 // fog color was already set
6397 // update the fog texture
6398 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)
6399 R_BuildFogTexture();
6400 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6401 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6404 r_refdef.fogenabled = false;
6406 switch(vid.renderpath)
6408 case RENDERPATH_GL20:
6409 case RENDERPATH_D3D9:
6410 case RENDERPATH_D3D10:
6411 case RENDERPATH_D3D11:
6412 case RENDERPATH_SOFT:
6413 case RENDERPATH_GLES2:
6414 if(v_glslgamma.integer && !vid_gammatables_trivial)
6416 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6418 // build GLSL gamma texture
6419 #define RAMPWIDTH 256
6420 unsigned short ramp[RAMPWIDTH * 3];
6421 unsigned char rampbgr[RAMPWIDTH][4];
6424 r_texture_gammaramps_serial = vid_gammatables_serial;
6426 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6427 for(i = 0; i < RAMPWIDTH; ++i)
6429 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6430 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6431 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6434 if (r_texture_gammaramps)
6436 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6440 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6446 // remove GLSL gamma texture
6449 case RENDERPATH_GL13:
6450 case RENDERPATH_GL11:
6455 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6456 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6462 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6463 if( scenetype != r_currentscenetype ) {
6464 // store the old scenetype
6465 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6466 r_currentscenetype = scenetype;
6467 // move in the new scene
6468 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6477 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6479 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6480 if( scenetype == r_currentscenetype ) {
6481 return &r_refdef.scene;
6483 return &r_scenes_store[ scenetype ];
6492 int dpsoftrast_test;
6493 void R_RenderView(void)
6495 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6497 dpsoftrast_test = r_test.integer;
6499 if (r_timereport_active)
6500 R_TimeReport("start");
6501 r_textureframe++; // used only by R_GetCurrentTexture
6502 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6504 if(R_CompileShader_CheckStaticParms())
6507 if (!r_drawentities.integer)
6508 r_refdef.scene.numentities = 0;
6510 R_AnimCache_ClearCache();
6511 R_FrameData_NewFrame();
6513 /* adjust for stereo display */
6514 if(R_Stereo_Active())
6516 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);
6517 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6520 if (r_refdef.view.isoverlay)
6522 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6523 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6524 R_TimeReport("depthclear");
6526 r_refdef.view.showdebug = false;
6528 r_waterstate.enabled = false;
6529 r_waterstate.numwaterplanes = 0;
6533 r_refdef.view.matrix = originalmatrix;
6539 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6541 r_refdef.view.matrix = originalmatrix;
6542 return; //Host_Error ("R_RenderView: NULL worldmodel");
6545 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6547 R_RenderView_UpdateViewVectors();
6549 R_Shadow_UpdateWorldLightSelection();
6551 R_Bloom_StartFrame();
6552 R_Water_StartFrame();
6555 if (r_timereport_active)
6556 R_TimeReport("viewsetup");
6558 R_ResetViewRendering3D();
6560 if (r_refdef.view.clear || r_refdef.fogenabled)
6562 R_ClearScreen(r_refdef.fogenabled);
6563 if (r_timereport_active)
6564 R_TimeReport("viewclear");
6566 r_refdef.view.clear = true;
6568 // this produces a bloom texture to be used in R_BlendView() later
6569 if (r_bloomstate.hdr)
6571 R_HDR_RenderBloomTexture();
6572 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6573 r_textureframe++; // used only by R_GetCurrentTexture
6576 r_refdef.view.showdebug = true;
6579 if (r_timereport_active)
6580 R_TimeReport("visibility");
6582 r_waterstate.numwaterplanes = 0;
6583 if (r_waterstate.enabled)
6584 R_RenderWaterPlanes();
6587 r_waterstate.numwaterplanes = 0;
6590 if (r_timereport_active)
6591 R_TimeReport("blendview");
6593 GL_Scissor(0, 0, vid.width, vid.height);
6594 GL_ScissorTest(false);
6596 r_refdef.view.matrix = originalmatrix;
6601 void R_RenderWaterPlanes(void)
6603 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6605 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6606 if (r_timereport_active)
6607 R_TimeReport("waterworld");
6610 // don't let sound skip if going slow
6611 if (r_refdef.scene.extraupdate)
6614 R_DrawModelsAddWaterPlanes();
6615 if (r_timereport_active)
6616 R_TimeReport("watermodels");
6618 if (r_waterstate.numwaterplanes)
6620 R_Water_ProcessPlanes();
6621 if (r_timereport_active)
6622 R_TimeReport("waterscenes");
6626 extern void R_DrawLightningBeams (void);
6627 extern void VM_CL_AddPolygonsToMeshQueue (void);
6628 extern void R_DrawPortals (void);
6629 extern cvar_t cl_locs_show;
6630 static void R_DrawLocs(void);
6631 static void R_DrawEntityBBoxes(void);
6632 static void R_DrawModelDecals(void);
6633 extern void R_DrawModelShadows(void);
6634 extern void R_DrawModelShadowMaps(void);
6635 extern cvar_t cl_decals_newsystem;
6636 extern qboolean r_shadow_usingdeferredprepass;
6637 void R_RenderScene(void)
6639 qboolean shadowmapping = false;
6641 if (r_timereport_active)
6642 R_TimeReport("beginscene");
6644 r_refdef.stats.renders++;
6648 // don't let sound skip if going slow
6649 if (r_refdef.scene.extraupdate)
6652 R_MeshQueue_BeginScene();
6656 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);
6658 if (r_timereport_active)
6659 R_TimeReport("skystartframe");
6661 if (cl.csqc_vidvars.drawworld)
6663 // don't let sound skip if going slow
6664 if (r_refdef.scene.extraupdate)
6667 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6669 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6670 if (r_timereport_active)
6671 R_TimeReport("worldsky");
6674 if (R_DrawBrushModelsSky() && r_timereport_active)
6675 R_TimeReport("bmodelsky");
6677 if (skyrendermasked && skyrenderlater)
6679 // we have to force off the water clipping plane while rendering sky
6683 if (r_timereport_active)
6684 R_TimeReport("sky");
6688 R_AnimCache_CacheVisibleEntities();
6689 if (r_timereport_active)
6690 R_TimeReport("animation");
6692 R_Shadow_PrepareLights();
6693 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6694 R_Shadow_PrepareModelShadows();
6695 if (r_timereport_active)
6696 R_TimeReport("preparelights");
6698 if (R_Shadow_ShadowMappingEnabled())
6699 shadowmapping = true;
6701 if (r_shadow_usingdeferredprepass)
6702 R_Shadow_DrawPrepass();
6704 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6706 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6707 if (r_timereport_active)
6708 R_TimeReport("worlddepth");
6710 if (r_depthfirst.integer >= 2)
6712 R_DrawModelsDepth();
6713 if (r_timereport_active)
6714 R_TimeReport("modeldepth");
6717 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6719 R_DrawModelShadowMaps();
6720 R_ResetViewRendering3D();
6721 // don't let sound skip if going slow
6722 if (r_refdef.scene.extraupdate)
6726 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6728 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6729 if (r_timereport_active)
6730 R_TimeReport("world");
6733 // don't let sound skip if going slow
6734 if (r_refdef.scene.extraupdate)
6738 if (r_timereport_active)
6739 R_TimeReport("models");
6741 // don't let sound skip if going slow
6742 if (r_refdef.scene.extraupdate)
6745 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6747 R_DrawModelShadows();
6748 R_ResetViewRendering3D();
6749 // don't let sound skip if going slow
6750 if (r_refdef.scene.extraupdate)
6754 if (!r_shadow_usingdeferredprepass)
6756 R_Shadow_DrawLights();
6757 if (r_timereport_active)
6758 R_TimeReport("rtlights");
6761 // don't let sound skip if going slow
6762 if (r_refdef.scene.extraupdate)
6765 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6767 R_DrawModelShadows();
6768 R_ResetViewRendering3D();
6769 // don't let sound skip if going slow
6770 if (r_refdef.scene.extraupdate)
6774 if (cl.csqc_vidvars.drawworld)
6776 if (cl_decals_newsystem.integer)
6778 R_DrawModelDecals();
6779 if (r_timereport_active)
6780 R_TimeReport("modeldecals");
6785 if (r_timereport_active)
6786 R_TimeReport("decals");
6790 if (r_timereport_active)
6791 R_TimeReport("particles");
6794 if (r_timereport_active)
6795 R_TimeReport("explosions");
6797 R_DrawLightningBeams();
6798 if (r_timereport_active)
6799 R_TimeReport("lightning");
6802 VM_CL_AddPolygonsToMeshQueue();
6804 if (r_refdef.view.showdebug)
6806 if (cl_locs_show.integer)
6809 if (r_timereport_active)
6810 R_TimeReport("showlocs");
6813 if (r_drawportals.integer)
6816 if (r_timereport_active)
6817 R_TimeReport("portals");
6820 if (r_showbboxes.value > 0)
6822 R_DrawEntityBBoxes();
6823 if (r_timereport_active)
6824 R_TimeReport("bboxes");
6828 R_MeshQueue_RenderTransparent();
6829 if (r_timereport_active)
6830 R_TimeReport("drawtrans");
6832 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))
6834 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6835 if (r_timereport_active)
6836 R_TimeReport("worlddebug");
6837 R_DrawModelsDebug();
6838 if (r_timereport_active)
6839 R_TimeReport("modeldebug");
6842 if (cl.csqc_vidvars.drawworld)
6844 R_Shadow_DrawCoronas();
6845 if (r_timereport_active)
6846 R_TimeReport("coronas");
6851 GL_DepthTest(false);
6852 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6853 GL_Color(1, 1, 1, 1);
6854 qglBegin(GL_POLYGON);
6855 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6856 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6857 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6858 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6860 qglBegin(GL_POLYGON);
6861 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]);
6862 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]);
6863 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]);
6864 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]);
6866 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6870 // don't let sound skip if going slow
6871 if (r_refdef.scene.extraupdate)
6874 R_ResetViewRendering2D();
6877 static const unsigned short bboxelements[36] =
6887 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6890 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6892 RSurf_ActiveWorldEntity();
6894 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6895 GL_DepthMask(false);
6896 GL_DepthRange(0, 1);
6897 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6898 // R_Mesh_ResetTextureState();
6900 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6901 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6902 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6903 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6904 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6905 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6906 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6907 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6908 R_FillColors(color4f, 8, cr, cg, cb, ca);
6909 if (r_refdef.fogenabled)
6911 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6913 f1 = RSurf_FogVertex(v);
6915 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6916 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6917 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6920 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6921 R_Mesh_ResetTextureState();
6922 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6923 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6926 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6930 prvm_edict_t *edict;
6931 prvm_prog_t *prog_save = prog;
6933 // this function draws bounding boxes of server entities
6937 GL_CullFace(GL_NONE);
6938 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6942 for (i = 0;i < numsurfaces;i++)
6944 edict = PRVM_EDICT_NUM(surfacelist[i]);
6945 switch ((int)edict->fields.server->solid)
6947 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
6948 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
6949 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
6950 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6951 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
6952 default: Vector4Set(color, 0, 0, 0, 0.50);break;
6954 color[3] *= r_showbboxes.value;
6955 color[3] = bound(0, color[3], 1);
6956 GL_DepthTest(!r_showdisabledepthtest.integer);
6957 GL_CullFace(r_refdef.view.cullface_front);
6958 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6964 static void R_DrawEntityBBoxes(void)
6967 prvm_edict_t *edict;
6969 prvm_prog_t *prog_save = prog;
6971 // this function draws bounding boxes of server entities
6977 for (i = 0;i < prog->num_edicts;i++)
6979 edict = PRVM_EDICT_NUM(i);
6980 if (edict->priv.server->free)
6982 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6983 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
6985 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
6987 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
6988 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
6994 static const int nomodelelement3i[24] =
7006 static const unsigned short nomodelelement3s[24] =
7018 static const float nomodelvertex3f[6*3] =
7028 static const float nomodelcolor4f[6*4] =
7030 0.0f, 0.0f, 0.5f, 1.0f,
7031 0.0f, 0.0f, 0.5f, 1.0f,
7032 0.0f, 0.5f, 0.0f, 1.0f,
7033 0.0f, 0.5f, 0.0f, 1.0f,
7034 0.5f, 0.0f, 0.0f, 1.0f,
7035 0.5f, 0.0f, 0.0f, 1.0f
7038 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7044 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);
7046 // this is only called once per entity so numsurfaces is always 1, and
7047 // surfacelist is always {0}, so this code does not handle batches
7049 if (rsurface.ent_flags & RENDER_ADDITIVE)
7051 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7052 GL_DepthMask(false);
7054 else if (rsurface.colormod[3] < 1)
7056 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7057 GL_DepthMask(false);
7061 GL_BlendFunc(GL_ONE, GL_ZERO);
7064 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7065 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7066 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7067 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7068 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7069 for (i = 0, c = color4f;i < 6;i++, c += 4)
7071 c[0] *= rsurface.colormod[0];
7072 c[1] *= rsurface.colormod[1];
7073 c[2] *= rsurface.colormod[2];
7074 c[3] *= rsurface.colormod[3];
7076 if (r_refdef.fogenabled)
7078 for (i = 0, c = color4f;i < 6;i++, c += 4)
7080 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7082 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7083 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7084 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7087 // R_Mesh_ResetTextureState();
7088 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7089 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7090 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7093 void R_DrawNoModel(entity_render_t *ent)
7096 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7097 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7098 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7100 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7103 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7105 vec3_t right1, right2, diff, normal;
7107 VectorSubtract (org2, org1, normal);
7109 // calculate 'right' vector for start
7110 VectorSubtract (r_refdef.view.origin, org1, diff);
7111 CrossProduct (normal, diff, right1);
7112 VectorNormalize (right1);
7114 // calculate 'right' vector for end
7115 VectorSubtract (r_refdef.view.origin, org2, diff);
7116 CrossProduct (normal, diff, right2);
7117 VectorNormalize (right2);
7119 vert[ 0] = org1[0] + width * right1[0];
7120 vert[ 1] = org1[1] + width * right1[1];
7121 vert[ 2] = org1[2] + width * right1[2];
7122 vert[ 3] = org1[0] - width * right1[0];
7123 vert[ 4] = org1[1] - width * right1[1];
7124 vert[ 5] = org1[2] - width * right1[2];
7125 vert[ 6] = org2[0] - width * right2[0];
7126 vert[ 7] = org2[1] - width * right2[1];
7127 vert[ 8] = org2[2] - width * right2[2];
7128 vert[ 9] = org2[0] + width * right2[0];
7129 vert[10] = org2[1] + width * right2[1];
7130 vert[11] = org2[2] + width * right2[2];
7133 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)
7135 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7136 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7137 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7138 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7139 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7140 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7141 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7142 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7143 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7144 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7145 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7146 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7149 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7154 VectorSet(v, x, y, z);
7155 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7156 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7158 if (i == mesh->numvertices)
7160 if (mesh->numvertices < mesh->maxvertices)
7162 VectorCopy(v, vertex3f);
7163 mesh->numvertices++;
7165 return mesh->numvertices;
7171 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7175 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7176 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7177 e = mesh->element3i + mesh->numtriangles * 3;
7178 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7180 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7181 if (mesh->numtriangles < mesh->maxtriangles)
7186 mesh->numtriangles++;
7188 element[1] = element[2];
7192 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7196 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7197 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7198 e = mesh->element3i + mesh->numtriangles * 3;
7199 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7201 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7202 if (mesh->numtriangles < mesh->maxtriangles)
7207 mesh->numtriangles++;
7209 element[1] = element[2];
7213 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7214 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7216 int planenum, planenum2;
7219 mplane_t *plane, *plane2;
7221 double temppoints[2][256*3];
7222 // figure out how large a bounding box we need to properly compute this brush
7224 for (w = 0;w < numplanes;w++)
7225 maxdist = max(maxdist, fabs(planes[w].dist));
7226 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7227 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7228 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7232 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7233 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7235 if (planenum2 == planenum)
7237 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);
7240 if (tempnumpoints < 3)
7242 // generate elements forming a triangle fan for this polygon
7243 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7247 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)
7249 texturelayer_t *layer;
7250 layer = t->currentlayers + t->currentnumlayers++;
7252 layer->depthmask = depthmask;
7253 layer->blendfunc1 = blendfunc1;
7254 layer->blendfunc2 = blendfunc2;
7255 layer->texture = texture;
7256 layer->texmatrix = *matrix;
7257 layer->color[0] = r;
7258 layer->color[1] = g;
7259 layer->color[2] = b;
7260 layer->color[3] = a;
7263 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7265 if(parms[0] == 0 && parms[1] == 0)
7267 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7268 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7273 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7276 index = parms[2] + r_refdef.scene.time * parms[3];
7277 index -= floor(index);
7278 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7281 case Q3WAVEFUNC_NONE:
7282 case Q3WAVEFUNC_NOISE:
7283 case Q3WAVEFUNC_COUNT:
7286 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7287 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7288 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7289 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7290 case Q3WAVEFUNC_TRIANGLE:
7292 f = index - floor(index);
7303 f = parms[0] + parms[1] * f;
7304 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7305 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7309 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7314 matrix4x4_t matrix, temp;
7315 switch(tcmod->tcmod)
7319 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7320 matrix = r_waterscrollmatrix;
7322 matrix = identitymatrix;
7324 case Q3TCMOD_ENTITYTRANSLATE:
7325 // this is used in Q3 to allow the gamecode to control texcoord
7326 // scrolling on the entity, which is not supported in darkplaces yet.
7327 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7329 case Q3TCMOD_ROTATE:
7330 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7331 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7332 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7335 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7337 case Q3TCMOD_SCROLL:
7338 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7340 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7341 w = (int) tcmod->parms[0];
7342 h = (int) tcmod->parms[1];
7343 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7345 idx = (int) floor(f * w * h);
7346 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7348 case Q3TCMOD_STRETCH:
7349 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7350 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7352 case Q3TCMOD_TRANSFORM:
7353 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7354 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7355 VectorSet(tcmat + 6, 0 , 0 , 1);
7356 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7357 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7359 case Q3TCMOD_TURBULENT:
7360 // this is handled in the RSurf_PrepareVertices function
7361 matrix = identitymatrix;
7365 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7368 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7370 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7371 char name[MAX_QPATH];
7372 skinframe_t *skinframe;
7373 unsigned char pixels[296*194];
7374 strlcpy(cache->name, skinname, sizeof(cache->name));
7375 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7376 if (developer_loading.integer)
7377 Con_Printf("loading %s\n", name);
7378 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7379 if (!skinframe || !skinframe->base)
7382 fs_offset_t filesize;
7384 f = FS_LoadFile(name, tempmempool, true, &filesize);
7387 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7388 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7392 cache->skinframe = skinframe;
7395 texture_t *R_GetCurrentTexture(texture_t *t)
7398 const entity_render_t *ent = rsurface.entity;
7399 dp_model_t *model = ent->model;
7400 q3shaderinfo_layer_tcmod_t *tcmod;
7402 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7403 return t->currentframe;
7404 t->update_lastrenderframe = r_textureframe;
7405 t->update_lastrenderentity = (void *)ent;
7407 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7408 t->camera_entity = ent->entitynumber;
7410 t->camera_entity = 0;
7412 // switch to an alternate material if this is a q1bsp animated material
7414 texture_t *texture = t;
7415 int s = rsurface.ent_skinnum;
7416 if ((unsigned int)s >= (unsigned int)model->numskins)
7418 if (model->skinscenes)
7420 if (model->skinscenes[s].framecount > 1)
7421 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7423 s = model->skinscenes[s].firstframe;
7426 t = t + s * model->num_surfaces;
7429 // use an alternate animation if the entity's frame is not 0,
7430 // and only if the texture has an alternate animation
7431 if (rsurface.ent_alttextures && t->anim_total[1])
7432 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7434 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7436 texture->currentframe = t;
7439 // update currentskinframe to be a qw skin or animation frame
7440 if (rsurface.ent_qwskin >= 0)
7442 i = rsurface.ent_qwskin;
7443 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7445 r_qwskincache_size = cl.maxclients;
7447 Mem_Free(r_qwskincache);
7448 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7450 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7451 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7452 t->currentskinframe = r_qwskincache[i].skinframe;
7453 if (t->currentskinframe == NULL)
7454 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7456 else if (t->numskinframes >= 2)
7457 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7458 if (t->backgroundnumskinframes >= 2)
7459 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7461 t->currentmaterialflags = t->basematerialflags;
7462 t->currentalpha = rsurface.colormod[3];
7463 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7464 t->currentalpha *= r_wateralpha.value;
7465 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7466 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7467 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7468 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7469 if (!(rsurface.ent_flags & RENDER_LIGHT))
7470 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7471 else if (FAKELIGHT_ENABLED)
7473 // no modellight if using fakelight for the map
7475 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7477 // pick a model lighting mode
7478 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7479 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7481 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7483 if (rsurface.ent_flags & RENDER_ADDITIVE)
7484 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7485 else if (t->currentalpha < 1)
7486 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7487 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7488 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7489 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7490 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7491 if (t->backgroundnumskinframes)
7492 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7493 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7495 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7496 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7499 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7500 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7501 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7503 // there is no tcmod
7504 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7506 t->currenttexmatrix = r_waterscrollmatrix;
7507 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7509 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7511 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7512 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7515 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7516 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7517 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7518 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7520 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7521 if (t->currentskinframe->qpixels)
7522 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7523 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7524 if (!t->basetexture)
7525 t->basetexture = r_texture_notexture;
7526 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7527 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7528 t->nmaptexture = t->currentskinframe->nmap;
7529 if (!t->nmaptexture)
7530 t->nmaptexture = r_texture_blanknormalmap;
7531 t->glosstexture = r_texture_black;
7532 t->glowtexture = t->currentskinframe->glow;
7533 t->fogtexture = t->currentskinframe->fog;
7534 t->reflectmasktexture = t->currentskinframe->reflect;
7535 if (t->backgroundnumskinframes)
7537 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7538 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7539 t->backgroundglosstexture = r_texture_black;
7540 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7541 if (!t->backgroundnmaptexture)
7542 t->backgroundnmaptexture = r_texture_blanknormalmap;
7546 t->backgroundbasetexture = r_texture_white;
7547 t->backgroundnmaptexture = r_texture_blanknormalmap;
7548 t->backgroundglosstexture = r_texture_black;
7549 t->backgroundglowtexture = NULL;
7551 t->specularpower = r_shadow_glossexponent.value;
7552 // TODO: store reference values for these in the texture?
7553 t->specularscale = 0;
7554 if (r_shadow_gloss.integer > 0)
7556 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7558 if (r_shadow_glossintensity.value > 0)
7560 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7561 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7562 t->specularscale = r_shadow_glossintensity.value;
7565 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7567 t->glosstexture = r_texture_white;
7568 t->backgroundglosstexture = r_texture_white;
7569 t->specularscale = r_shadow_gloss2intensity.value;
7570 t->specularpower = r_shadow_gloss2exponent.value;
7573 t->specularscale *= t->specularscalemod;
7574 t->specularpower *= t->specularpowermod;
7576 // lightmaps mode looks bad with dlights using actual texturing, so turn
7577 // off the colormap and glossmap, but leave the normalmap on as it still
7578 // accurately represents the shading involved
7579 if (gl_lightmaps.integer)
7581 t->basetexture = r_texture_grey128;
7582 t->pantstexture = r_texture_black;
7583 t->shirttexture = r_texture_black;
7584 t->nmaptexture = r_texture_blanknormalmap;
7585 t->glosstexture = r_texture_black;
7586 t->glowtexture = NULL;
7587 t->fogtexture = NULL;
7588 t->reflectmasktexture = NULL;
7589 t->backgroundbasetexture = NULL;
7590 t->backgroundnmaptexture = r_texture_blanknormalmap;
7591 t->backgroundglosstexture = r_texture_black;
7592 t->backgroundglowtexture = NULL;
7593 t->specularscale = 0;
7594 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7597 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7598 VectorClear(t->dlightcolor);
7599 t->currentnumlayers = 0;
7600 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7602 int blendfunc1, blendfunc2;
7604 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7606 blendfunc1 = GL_SRC_ALPHA;
7607 blendfunc2 = GL_ONE;
7609 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7611 blendfunc1 = GL_SRC_ALPHA;
7612 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7614 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7616 blendfunc1 = t->customblendfunc[0];
7617 blendfunc2 = t->customblendfunc[1];
7621 blendfunc1 = GL_ONE;
7622 blendfunc2 = GL_ZERO;
7624 // don't colormod evilblend textures
7625 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7626 VectorSet(t->lightmapcolor, 1, 1, 1);
7627 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7628 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7630 // fullbright is not affected by r_refdef.lightmapintensity
7631 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]);
7632 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7633 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]);
7634 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7635 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]);
7639 vec3_t ambientcolor;
7641 // set the color tint used for lights affecting this surface
7642 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7644 // q3bsp has no lightmap updates, so the lightstylevalue that
7645 // would normally be baked into the lightmap must be
7646 // applied to the color
7647 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7648 if (model->type == mod_brushq3)
7649 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7650 colorscale *= r_refdef.lightmapintensity;
7651 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7652 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7653 // basic lit geometry
7654 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]);
7655 // add pants/shirt if needed
7656 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7657 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]);
7658 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7659 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]);
7660 // now add ambient passes if needed
7661 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7663 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]);
7664 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7665 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]);
7666 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7667 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]);
7670 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7671 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]);
7672 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7674 // if this is opaque use alpha blend which will darken the earlier
7677 // if this is an alpha blended material, all the earlier passes
7678 // were darkened by fog already, so we only need to add the fog
7679 // color ontop through the fog mask texture
7681 // if this is an additive blended material, all the earlier passes
7682 // were darkened by fog already, and we should not add fog color
7683 // (because the background was not darkened, there is no fog color
7684 // that was lost behind it).
7685 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]);
7689 return t->currentframe;
7692 rsurfacestate_t rsurface;
7694 void RSurf_ActiveWorldEntity(void)
7696 dp_model_t *model = r_refdef.scene.worldmodel;
7697 //if (rsurface.entity == r_refdef.scene.worldentity)
7699 rsurface.entity = r_refdef.scene.worldentity;
7700 rsurface.skeleton = NULL;
7701 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7702 rsurface.ent_skinnum = 0;
7703 rsurface.ent_qwskin = -1;
7704 rsurface.ent_shadertime = 0;
7705 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7706 rsurface.matrix = identitymatrix;
7707 rsurface.inversematrix = identitymatrix;
7708 rsurface.matrixscale = 1;
7709 rsurface.inversematrixscale = 1;
7710 R_EntityMatrix(&identitymatrix);
7711 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7712 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7713 rsurface.fograngerecip = r_refdef.fograngerecip;
7714 rsurface.fogheightfade = r_refdef.fogheightfade;
7715 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7716 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7717 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7718 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7719 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7720 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7721 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7722 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7723 rsurface.colormod[3] = 1;
7724 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);
7725 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7726 rsurface.frameblend[0].lerp = 1;
7727 rsurface.ent_alttextures = false;
7728 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7729 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7730 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7731 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7732 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7733 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7734 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7735 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7736 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7737 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7738 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7739 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7740 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7741 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7742 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7743 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7744 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7745 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7746 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7747 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7748 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7749 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7750 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7751 rsurface.modelelement3i = model->surfmesh.data_element3i;
7752 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7753 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7754 rsurface.modelelement3s = model->surfmesh.data_element3s;
7755 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7756 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7757 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7758 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7759 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7760 rsurface.modelsurfaces = model->data_surfaces;
7761 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7762 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7763 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7764 rsurface.modelgeneratedvertex = false;
7765 rsurface.batchgeneratedvertex = false;
7766 rsurface.batchfirstvertex = 0;
7767 rsurface.batchnumvertices = 0;
7768 rsurface.batchfirsttriangle = 0;
7769 rsurface.batchnumtriangles = 0;
7770 rsurface.batchvertex3f = NULL;
7771 rsurface.batchvertex3f_vertexbuffer = NULL;
7772 rsurface.batchvertex3f_bufferoffset = 0;
7773 rsurface.batchsvector3f = NULL;
7774 rsurface.batchsvector3f_vertexbuffer = NULL;
7775 rsurface.batchsvector3f_bufferoffset = 0;
7776 rsurface.batchtvector3f = NULL;
7777 rsurface.batchtvector3f_vertexbuffer = NULL;
7778 rsurface.batchtvector3f_bufferoffset = 0;
7779 rsurface.batchnormal3f = NULL;
7780 rsurface.batchnormal3f_vertexbuffer = NULL;
7781 rsurface.batchnormal3f_bufferoffset = 0;
7782 rsurface.batchlightmapcolor4f = NULL;
7783 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7784 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7785 rsurface.batchtexcoordtexture2f = NULL;
7786 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7787 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7788 rsurface.batchtexcoordlightmap2f = NULL;
7789 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7790 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7791 rsurface.batchvertexmesh = NULL;
7792 rsurface.batchvertexmeshbuffer = NULL;
7793 rsurface.batchvertex3fbuffer = NULL;
7794 rsurface.batchelement3i = NULL;
7795 rsurface.batchelement3i_indexbuffer = NULL;
7796 rsurface.batchelement3i_bufferoffset = 0;
7797 rsurface.batchelement3s = NULL;
7798 rsurface.batchelement3s_indexbuffer = NULL;
7799 rsurface.batchelement3s_bufferoffset = 0;
7800 rsurface.passcolor4f = NULL;
7801 rsurface.passcolor4f_vertexbuffer = NULL;
7802 rsurface.passcolor4f_bufferoffset = 0;
7805 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7807 dp_model_t *model = ent->model;
7808 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7810 rsurface.entity = (entity_render_t *)ent;
7811 rsurface.skeleton = ent->skeleton;
7812 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7813 rsurface.ent_skinnum = ent->skinnum;
7814 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;
7815 rsurface.ent_shadertime = ent->shadertime;
7816 rsurface.ent_flags = ent->flags;
7817 rsurface.matrix = ent->matrix;
7818 rsurface.inversematrix = ent->inversematrix;
7819 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7820 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7821 R_EntityMatrix(&rsurface.matrix);
7822 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7823 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7824 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7825 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7826 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7827 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7828 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7829 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7830 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7831 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7832 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7833 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7834 rsurface.colormod[3] = ent->alpha;
7835 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7836 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7837 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7838 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7839 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7840 if (ent->model->brush.submodel && !prepass)
7842 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7843 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7845 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7847 if (ent->animcache_vertex3f)
7849 rsurface.modelvertex3f = ent->animcache_vertex3f;
7850 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7851 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7852 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7853 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7854 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7855 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7857 else if (wanttangents)
7859 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7860 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7861 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7862 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7863 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7864 rsurface.modelvertexmesh = NULL;
7865 rsurface.modelvertexmeshbuffer = NULL;
7866 rsurface.modelvertex3fbuffer = NULL;
7868 else if (wantnormals)
7870 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7871 rsurface.modelsvector3f = NULL;
7872 rsurface.modeltvector3f = NULL;
7873 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7874 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7875 rsurface.modelvertexmesh = NULL;
7876 rsurface.modelvertexmeshbuffer = NULL;
7877 rsurface.modelvertex3fbuffer = NULL;
7881 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7882 rsurface.modelsvector3f = NULL;
7883 rsurface.modeltvector3f = NULL;
7884 rsurface.modelnormal3f = NULL;
7885 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7886 rsurface.modelvertexmesh = NULL;
7887 rsurface.modelvertexmeshbuffer = NULL;
7888 rsurface.modelvertex3fbuffer = NULL;
7890 rsurface.modelvertex3f_vertexbuffer = 0;
7891 rsurface.modelvertex3f_bufferoffset = 0;
7892 rsurface.modelsvector3f_vertexbuffer = 0;
7893 rsurface.modelsvector3f_bufferoffset = 0;
7894 rsurface.modeltvector3f_vertexbuffer = 0;
7895 rsurface.modeltvector3f_bufferoffset = 0;
7896 rsurface.modelnormal3f_vertexbuffer = 0;
7897 rsurface.modelnormal3f_bufferoffset = 0;
7898 rsurface.modelgeneratedvertex = true;
7902 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7903 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7904 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7905 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7906 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7907 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7908 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7909 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7910 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7911 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7912 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7913 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7914 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7915 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7916 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7917 rsurface.modelgeneratedvertex = false;
7919 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7920 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7921 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7922 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7923 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7924 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7925 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7926 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7927 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7928 rsurface.modelelement3i = model->surfmesh.data_element3i;
7929 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7930 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7931 rsurface.modelelement3s = model->surfmesh.data_element3s;
7932 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7933 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7934 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7935 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7936 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7937 rsurface.modelsurfaces = model->data_surfaces;
7938 rsurface.batchgeneratedvertex = false;
7939 rsurface.batchfirstvertex = 0;
7940 rsurface.batchnumvertices = 0;
7941 rsurface.batchfirsttriangle = 0;
7942 rsurface.batchnumtriangles = 0;
7943 rsurface.batchvertex3f = NULL;
7944 rsurface.batchvertex3f_vertexbuffer = NULL;
7945 rsurface.batchvertex3f_bufferoffset = 0;
7946 rsurface.batchsvector3f = NULL;
7947 rsurface.batchsvector3f_vertexbuffer = NULL;
7948 rsurface.batchsvector3f_bufferoffset = 0;
7949 rsurface.batchtvector3f = NULL;
7950 rsurface.batchtvector3f_vertexbuffer = NULL;
7951 rsurface.batchtvector3f_bufferoffset = 0;
7952 rsurface.batchnormal3f = NULL;
7953 rsurface.batchnormal3f_vertexbuffer = NULL;
7954 rsurface.batchnormal3f_bufferoffset = 0;
7955 rsurface.batchlightmapcolor4f = NULL;
7956 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7957 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7958 rsurface.batchtexcoordtexture2f = NULL;
7959 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7960 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7961 rsurface.batchtexcoordlightmap2f = NULL;
7962 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7963 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7964 rsurface.batchvertexmesh = NULL;
7965 rsurface.batchvertexmeshbuffer = NULL;
7966 rsurface.batchvertex3fbuffer = NULL;
7967 rsurface.batchelement3i = NULL;
7968 rsurface.batchelement3i_indexbuffer = NULL;
7969 rsurface.batchelement3i_bufferoffset = 0;
7970 rsurface.batchelement3s = NULL;
7971 rsurface.batchelement3s_indexbuffer = NULL;
7972 rsurface.batchelement3s_bufferoffset = 0;
7973 rsurface.passcolor4f = NULL;
7974 rsurface.passcolor4f_vertexbuffer = NULL;
7975 rsurface.passcolor4f_bufferoffset = 0;
7978 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)
7980 rsurface.entity = r_refdef.scene.worldentity;
7981 rsurface.skeleton = NULL;
7982 rsurface.ent_skinnum = 0;
7983 rsurface.ent_qwskin = -1;
7984 rsurface.ent_shadertime = shadertime;
7985 rsurface.ent_flags = entflags;
7986 rsurface.modelnumvertices = numvertices;
7987 rsurface.modelnumtriangles = numtriangles;
7988 rsurface.matrix = *matrix;
7989 rsurface.inversematrix = *inversematrix;
7990 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7991 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7992 R_EntityMatrix(&rsurface.matrix);
7993 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7994 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7995 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7996 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7997 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7998 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7999 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8000 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8001 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8002 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8003 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8004 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8005 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);
8006 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8007 rsurface.frameblend[0].lerp = 1;
8008 rsurface.ent_alttextures = false;
8009 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8010 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8013 rsurface.modelvertex3f = (float *)vertex3f;
8014 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8015 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8016 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8018 else if (wantnormals)
8020 rsurface.modelvertex3f = (float *)vertex3f;
8021 rsurface.modelsvector3f = NULL;
8022 rsurface.modeltvector3f = NULL;
8023 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8027 rsurface.modelvertex3f = (float *)vertex3f;
8028 rsurface.modelsvector3f = NULL;
8029 rsurface.modeltvector3f = NULL;
8030 rsurface.modelnormal3f = NULL;
8032 rsurface.modelvertexmesh = NULL;
8033 rsurface.modelvertexmeshbuffer = NULL;
8034 rsurface.modelvertex3fbuffer = NULL;
8035 rsurface.modelvertex3f_vertexbuffer = 0;
8036 rsurface.modelvertex3f_bufferoffset = 0;
8037 rsurface.modelsvector3f_vertexbuffer = 0;
8038 rsurface.modelsvector3f_bufferoffset = 0;
8039 rsurface.modeltvector3f_vertexbuffer = 0;
8040 rsurface.modeltvector3f_bufferoffset = 0;
8041 rsurface.modelnormal3f_vertexbuffer = 0;
8042 rsurface.modelnormal3f_bufferoffset = 0;
8043 rsurface.modelgeneratedvertex = true;
8044 rsurface.modellightmapcolor4f = (float *)color4f;
8045 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8046 rsurface.modellightmapcolor4f_bufferoffset = 0;
8047 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8048 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8049 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8050 rsurface.modeltexcoordlightmap2f = NULL;
8051 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8052 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8053 rsurface.modelelement3i = (int *)element3i;
8054 rsurface.modelelement3i_indexbuffer = NULL;
8055 rsurface.modelelement3i_bufferoffset = 0;
8056 rsurface.modelelement3s = (unsigned short *)element3s;
8057 rsurface.modelelement3s_indexbuffer = NULL;
8058 rsurface.modelelement3s_bufferoffset = 0;
8059 rsurface.modellightmapoffsets = NULL;
8060 rsurface.modelsurfaces = NULL;
8061 rsurface.batchgeneratedvertex = false;
8062 rsurface.batchfirstvertex = 0;
8063 rsurface.batchnumvertices = 0;
8064 rsurface.batchfirsttriangle = 0;
8065 rsurface.batchnumtriangles = 0;
8066 rsurface.batchvertex3f = NULL;
8067 rsurface.batchvertex3f_vertexbuffer = NULL;
8068 rsurface.batchvertex3f_bufferoffset = 0;
8069 rsurface.batchsvector3f = NULL;
8070 rsurface.batchsvector3f_vertexbuffer = NULL;
8071 rsurface.batchsvector3f_bufferoffset = 0;
8072 rsurface.batchtvector3f = NULL;
8073 rsurface.batchtvector3f_vertexbuffer = NULL;
8074 rsurface.batchtvector3f_bufferoffset = 0;
8075 rsurface.batchnormal3f = NULL;
8076 rsurface.batchnormal3f_vertexbuffer = NULL;
8077 rsurface.batchnormal3f_bufferoffset = 0;
8078 rsurface.batchlightmapcolor4f = NULL;
8079 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8080 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8081 rsurface.batchtexcoordtexture2f = NULL;
8082 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8083 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8084 rsurface.batchtexcoordlightmap2f = NULL;
8085 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8086 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8087 rsurface.batchvertexmesh = NULL;
8088 rsurface.batchvertexmeshbuffer = NULL;
8089 rsurface.batchvertex3fbuffer = NULL;
8090 rsurface.batchelement3i = NULL;
8091 rsurface.batchelement3i_indexbuffer = NULL;
8092 rsurface.batchelement3i_bufferoffset = 0;
8093 rsurface.batchelement3s = NULL;
8094 rsurface.batchelement3s_indexbuffer = NULL;
8095 rsurface.batchelement3s_bufferoffset = 0;
8096 rsurface.passcolor4f = NULL;
8097 rsurface.passcolor4f_vertexbuffer = NULL;
8098 rsurface.passcolor4f_bufferoffset = 0;
8100 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8102 if ((wantnormals || wanttangents) && !normal3f)
8104 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8105 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8107 if (wanttangents && !svector3f)
8109 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8110 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8111 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8116 float RSurf_FogPoint(const float *v)
8118 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8119 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8120 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8121 float FogHeightFade = r_refdef.fogheightfade;
8123 unsigned int fogmasktableindex;
8124 if (r_refdef.fogplaneviewabove)
8125 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8127 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8128 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8129 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8132 float RSurf_FogVertex(const float *v)
8134 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8135 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8136 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8137 float FogHeightFade = rsurface.fogheightfade;
8139 unsigned int fogmasktableindex;
8140 if (r_refdef.fogplaneviewabove)
8141 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8143 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8144 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8145 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8148 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8151 for (i = 0;i < numelements;i++)
8152 outelement3i[i] = inelement3i[i] + adjust;
8155 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8156 extern cvar_t gl_vbo;
8157 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8165 int surfacefirsttriangle;
8166 int surfacenumtriangles;
8167 int surfacefirstvertex;
8168 int surfaceendvertex;
8169 int surfacenumvertices;
8170 int batchnumvertices;
8171 int batchnumtriangles;
8175 qboolean dynamicvertex;
8179 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8181 q3shaderinfo_deform_t *deform;
8182 const msurface_t *surface, *firstsurface;
8183 r_vertexmesh_t *vertexmesh;
8184 if (!texturenumsurfaces)
8186 // find vertex range of this surface batch
8188 firstsurface = texturesurfacelist[0];
8189 firsttriangle = firstsurface->num_firsttriangle;
8190 batchnumvertices = 0;
8191 batchnumtriangles = 0;
8192 firstvertex = endvertex = firstsurface->num_firstvertex;
8193 for (i = 0;i < texturenumsurfaces;i++)
8195 surface = texturesurfacelist[i];
8196 if (surface != firstsurface + i)
8198 surfacefirstvertex = surface->num_firstvertex;
8199 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8200 surfacenumvertices = surface->num_vertices;
8201 surfacenumtriangles = surface->num_triangles;
8202 if (firstvertex > surfacefirstvertex)
8203 firstvertex = surfacefirstvertex;
8204 if (endvertex < surfaceendvertex)
8205 endvertex = surfaceendvertex;
8206 batchnumvertices += surfacenumvertices;
8207 batchnumtriangles += surfacenumtriangles;
8210 // we now know the vertex range used, and if there are any gaps in it
8211 rsurface.batchfirstvertex = firstvertex;
8212 rsurface.batchnumvertices = endvertex - firstvertex;
8213 rsurface.batchfirsttriangle = firsttriangle;
8214 rsurface.batchnumtriangles = batchnumtriangles;
8216 // this variable holds flags for which properties have been updated that
8217 // may require regenerating vertexmesh array...
8220 // check if any dynamic vertex processing must occur
8221 dynamicvertex = false;
8223 // if there is a chance of animated vertex colors, it's a dynamic batch
8224 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8226 dynamicvertex = true;
8227 batchneed |= BATCHNEED_NOGAPS;
8228 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8231 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8233 switch (deform->deform)
8236 case Q3DEFORM_PROJECTIONSHADOW:
8237 case Q3DEFORM_TEXT0:
8238 case Q3DEFORM_TEXT1:
8239 case Q3DEFORM_TEXT2:
8240 case Q3DEFORM_TEXT3:
8241 case Q3DEFORM_TEXT4:
8242 case Q3DEFORM_TEXT5:
8243 case Q3DEFORM_TEXT6:
8244 case Q3DEFORM_TEXT7:
8247 case Q3DEFORM_AUTOSPRITE:
8248 dynamicvertex = true;
8249 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8250 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8252 case Q3DEFORM_AUTOSPRITE2:
8253 dynamicvertex = true;
8254 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8255 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8257 case Q3DEFORM_NORMAL:
8258 dynamicvertex = true;
8259 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8260 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8263 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8264 break; // if wavefunc is a nop, ignore this transform
8265 dynamicvertex = true;
8266 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8267 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8269 case Q3DEFORM_BULGE:
8270 dynamicvertex = true;
8271 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8272 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8275 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8276 break; // if wavefunc is a nop, ignore this transform
8277 dynamicvertex = true;
8278 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8279 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8283 switch(rsurface.texture->tcgen.tcgen)
8286 case Q3TCGEN_TEXTURE:
8288 case Q3TCGEN_LIGHTMAP:
8289 dynamicvertex = true;
8290 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8291 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8293 case Q3TCGEN_VECTOR:
8294 dynamicvertex = true;
8295 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8296 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8298 case Q3TCGEN_ENVIRONMENT:
8299 dynamicvertex = true;
8300 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8301 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8304 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8306 dynamicvertex = true;
8307 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8308 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8311 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8313 dynamicvertex = true;
8314 batchneed |= BATCHNEED_NOGAPS;
8315 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8318 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8320 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8321 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8322 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8323 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8324 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8325 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8326 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8329 // when the model data has no vertex buffer (dynamic mesh), we need to
8331 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8332 batchneed |= BATCHNEED_NOGAPS;
8334 // if needsupdate, we have to do a dynamic vertex batch for sure
8335 if (needsupdate & batchneed)
8336 dynamicvertex = true;
8338 // see if we need to build vertexmesh from arrays
8339 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8340 dynamicvertex = true;
8342 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8343 // also some drivers strongly dislike firstvertex
8344 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8345 dynamicvertex = true;
8347 rsurface.batchvertex3f = rsurface.modelvertex3f;
8348 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8349 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8350 rsurface.batchsvector3f = rsurface.modelsvector3f;
8351 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8352 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8353 rsurface.batchtvector3f = rsurface.modeltvector3f;
8354 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8355 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8356 rsurface.batchnormal3f = rsurface.modelnormal3f;
8357 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8358 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8359 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8360 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8361 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8362 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8363 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8364 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8365 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8366 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8367 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8368 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8369 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8370 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8371 rsurface.batchelement3i = rsurface.modelelement3i;
8372 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8373 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8374 rsurface.batchelement3s = rsurface.modelelement3s;
8375 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8376 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8378 // if any dynamic vertex processing has to occur in software, we copy the
8379 // entire surface list together before processing to rebase the vertices
8380 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8382 // if any gaps exist and we do not have a static vertex buffer, we have to
8383 // copy the surface list together to avoid wasting upload bandwidth on the
8384 // vertices in the gaps.
8386 // if gaps exist and we have a static vertex buffer, we still have to
8387 // combine the index buffer ranges into one dynamic index buffer.
8389 // in all cases we end up with data that can be drawn in one call.
8393 // static vertex data, just set pointers...
8394 rsurface.batchgeneratedvertex = false;
8395 // if there are gaps, we want to build a combined index buffer,
8396 // otherwise use the original static buffer with an appropriate offset
8399 // build a new triangle elements array for this batch
8400 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8401 rsurface.batchfirsttriangle = 0;
8403 for (i = 0;i < texturenumsurfaces;i++)
8405 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8406 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8407 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8408 numtriangles += surfacenumtriangles;
8410 rsurface.batchelement3i_indexbuffer = NULL;
8411 rsurface.batchelement3i_bufferoffset = 0;
8412 rsurface.batchelement3s = NULL;
8413 rsurface.batchelement3s_indexbuffer = NULL;
8414 rsurface.batchelement3s_bufferoffset = 0;
8415 if (endvertex <= 65536)
8417 // make a 16bit (unsigned short) index array if possible
8418 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8419 for (i = 0;i < numtriangles*3;i++)
8420 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8426 // something needs software processing, do it for real...
8427 // we only directly handle separate array data in this case and then
8428 // generate interleaved data if needed...
8429 rsurface.batchgeneratedvertex = true;
8431 // now copy the vertex data into a combined array and make an index array
8432 // (this is what Quake3 does all the time)
8433 //if (gaps || rsurface.batchfirstvertex)
8435 rsurface.batchvertex3fbuffer = NULL;
8436 rsurface.batchvertexmesh = NULL;
8437 rsurface.batchvertexmeshbuffer = NULL;
8438 rsurface.batchvertex3f = NULL;
8439 rsurface.batchvertex3f_vertexbuffer = NULL;
8440 rsurface.batchvertex3f_bufferoffset = 0;
8441 rsurface.batchsvector3f = NULL;
8442 rsurface.batchsvector3f_vertexbuffer = NULL;
8443 rsurface.batchsvector3f_bufferoffset = 0;
8444 rsurface.batchtvector3f = NULL;
8445 rsurface.batchtvector3f_vertexbuffer = NULL;
8446 rsurface.batchtvector3f_bufferoffset = 0;
8447 rsurface.batchnormal3f = NULL;
8448 rsurface.batchnormal3f_vertexbuffer = NULL;
8449 rsurface.batchnormal3f_bufferoffset = 0;
8450 rsurface.batchlightmapcolor4f = NULL;
8451 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8452 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8453 rsurface.batchtexcoordtexture2f = NULL;
8454 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8455 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8456 rsurface.batchtexcoordlightmap2f = NULL;
8457 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8458 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8459 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8460 rsurface.batchelement3i_indexbuffer = NULL;
8461 rsurface.batchelement3i_bufferoffset = 0;
8462 rsurface.batchelement3s = NULL;
8463 rsurface.batchelement3s_indexbuffer = NULL;
8464 rsurface.batchelement3s_bufferoffset = 0;
8465 // we'll only be setting up certain arrays as needed
8466 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8467 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8468 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8469 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8470 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8471 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8472 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8474 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8475 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8477 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8478 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8479 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8480 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8481 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8482 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8485 for (i = 0;i < texturenumsurfaces;i++)
8487 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8488 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8489 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8490 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8491 // copy only the data requested
8492 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8493 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8494 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8496 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8497 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8498 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8499 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8500 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8502 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8503 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8505 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8506 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8507 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8508 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8509 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8510 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8512 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8513 numvertices += surfacenumvertices;
8514 numtriangles += surfacenumtriangles;
8517 // generate a 16bit index array as well if possible
8518 // (in general, dynamic batches fit)
8519 if (numvertices <= 65536)
8521 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8522 for (i = 0;i < numtriangles*3;i++)
8523 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8526 // since we've copied everything, the batch now starts at 0
8527 rsurface.batchfirstvertex = 0;
8528 rsurface.batchnumvertices = batchnumvertices;
8529 rsurface.batchfirsttriangle = 0;
8530 rsurface.batchnumtriangles = batchnumtriangles;
8533 // q1bsp surfaces rendered in vertex color mode have to have colors
8534 // calculated based on lightstyles
8535 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8537 // generate color arrays for the surfaces in this list
8542 const unsigned char *lm;
8543 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8544 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8545 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8547 for (i = 0;i < texturenumsurfaces;i++)
8549 surface = texturesurfacelist[i];
8550 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8551 surfacenumvertices = surface->num_vertices;
8552 if (surface->lightmapinfo->samples)
8554 for (j = 0;j < surfacenumvertices;j++)
8556 lm = surface->lightmapinfo->samples + offsets[j];
8557 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8558 VectorScale(lm, scale, c);
8559 if (surface->lightmapinfo->styles[1] != 255)
8561 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8563 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8564 VectorMA(c, scale, lm, c);
8565 if (surface->lightmapinfo->styles[2] != 255)
8568 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8569 VectorMA(c, scale, lm, c);
8570 if (surface->lightmapinfo->styles[3] != 255)
8573 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8574 VectorMA(c, scale, lm, c);
8581 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);
8587 for (j = 0;j < surfacenumvertices;j++)
8589 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8596 // if vertices are deformed (sprite flares and things in maps, possibly
8597 // water waves, bulges and other deformations), modify the copied vertices
8599 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8601 switch (deform->deform)
8604 case Q3DEFORM_PROJECTIONSHADOW:
8605 case Q3DEFORM_TEXT0:
8606 case Q3DEFORM_TEXT1:
8607 case Q3DEFORM_TEXT2:
8608 case Q3DEFORM_TEXT3:
8609 case Q3DEFORM_TEXT4:
8610 case Q3DEFORM_TEXT5:
8611 case Q3DEFORM_TEXT6:
8612 case Q3DEFORM_TEXT7:
8615 case Q3DEFORM_AUTOSPRITE:
8616 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8617 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8618 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8619 VectorNormalize(newforward);
8620 VectorNormalize(newright);
8621 VectorNormalize(newup);
8622 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8623 // rsurface.batchvertex3f_vertexbuffer = NULL;
8624 // rsurface.batchvertex3f_bufferoffset = 0;
8625 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8626 // rsurface.batchsvector3f_vertexbuffer = NULL;
8627 // rsurface.batchsvector3f_bufferoffset = 0;
8628 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8629 // rsurface.batchtvector3f_vertexbuffer = NULL;
8630 // rsurface.batchtvector3f_bufferoffset = 0;
8631 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8632 // rsurface.batchnormal3f_vertexbuffer = NULL;
8633 // rsurface.batchnormal3f_bufferoffset = 0;
8634 // a single autosprite surface can contain multiple sprites...
8635 for (j = 0;j < batchnumvertices - 3;j += 4)
8637 VectorClear(center);
8638 for (i = 0;i < 4;i++)
8639 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8640 VectorScale(center, 0.25f, center);
8641 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8642 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8643 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8644 for (i = 0;i < 4;i++)
8646 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8647 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8650 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8651 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8652 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
8654 case Q3DEFORM_AUTOSPRITE2:
8655 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8656 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8657 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8658 VectorNormalize(newforward);
8659 VectorNormalize(newright);
8660 VectorNormalize(newup);
8661 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8662 // rsurface.batchvertex3f_vertexbuffer = NULL;
8663 // rsurface.batchvertex3f_bufferoffset = 0;
8665 const float *v1, *v2;
8675 memset(shortest, 0, sizeof(shortest));
8676 // a single autosprite surface can contain multiple sprites...
8677 for (j = 0;j < batchnumvertices - 3;j += 4)
8679 VectorClear(center);
8680 for (i = 0;i < 4;i++)
8681 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8682 VectorScale(center, 0.25f, center);
8683 // find the two shortest edges, then use them to define the
8684 // axis vectors for rotating around the central axis
8685 for (i = 0;i < 6;i++)
8687 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8688 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8689 l = VectorDistance2(v1, v2);
8690 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8692 l += (1.0f / 1024.0f);
8693 if (shortest[0].length2 > l || i == 0)
8695 shortest[1] = shortest[0];
8696 shortest[0].length2 = l;
8697 shortest[0].v1 = v1;
8698 shortest[0].v2 = v2;
8700 else if (shortest[1].length2 > l || i == 1)
8702 shortest[1].length2 = l;
8703 shortest[1].v1 = v1;
8704 shortest[1].v2 = v2;
8707 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8708 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8709 // this calculates the right vector from the shortest edge
8710 // and the up vector from the edge midpoints
8711 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8712 VectorNormalize(right);
8713 VectorSubtract(end, start, up);
8714 VectorNormalize(up);
8715 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8716 VectorSubtract(rsurface.localvieworigin, center, forward);
8717 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8718 VectorNegate(forward, forward);
8719 VectorReflect(forward, 0, up, forward);
8720 VectorNormalize(forward);
8721 CrossProduct(up, forward, newright);
8722 VectorNormalize(newright);
8723 // rotate the quad around the up axis vector, this is made
8724 // especially easy by the fact we know the quad is flat,
8725 // so we only have to subtract the center position and
8726 // measure distance along the right vector, and then
8727 // multiply that by the newright vector and add back the
8729 // we also need to subtract the old position to undo the
8730 // displacement from the center, which we do with a
8731 // DotProduct, the subtraction/addition of center is also
8732 // optimized into DotProducts here
8733 l = DotProduct(right, center);
8734 for (i = 0;i < 4;i++)
8736 v1 = rsurface.batchvertex3f + 3*(j+i);
8737 f = DotProduct(right, v1) - l;
8738 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8742 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8744 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8745 // rsurface.batchnormal3f_vertexbuffer = NULL;
8746 // rsurface.batchnormal3f_bufferoffset = 0;
8747 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8749 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8751 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8752 // rsurface.batchsvector3f_vertexbuffer = NULL;
8753 // rsurface.batchsvector3f_bufferoffset = 0;
8754 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8755 // rsurface.batchtvector3f_vertexbuffer = NULL;
8756 // rsurface.batchtvector3f_bufferoffset = 0;
8757 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);
8760 case Q3DEFORM_NORMAL:
8761 // deform the normals to make reflections wavey
8762 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8763 rsurface.batchnormal3f_vertexbuffer = NULL;
8764 rsurface.batchnormal3f_bufferoffset = 0;
8765 for (j = 0;j < batchnumvertices;j++)
8768 float *normal = rsurface.batchnormal3f + 3*j;
8769 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8770 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8771 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]);
8772 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]);
8773 VectorNormalize(normal);
8775 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8777 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8778 // rsurface.batchsvector3f_vertexbuffer = NULL;
8779 // rsurface.batchsvector3f_bufferoffset = 0;
8780 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8781 // rsurface.batchtvector3f_vertexbuffer = NULL;
8782 // rsurface.batchtvector3f_bufferoffset = 0;
8783 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);
8787 // deform vertex array to make wavey water and flags and such
8788 waveparms[0] = deform->waveparms[0];
8789 waveparms[1] = deform->waveparms[1];
8790 waveparms[2] = deform->waveparms[2];
8791 waveparms[3] = deform->waveparms[3];
8792 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8793 break; // if wavefunc is a nop, don't make a dynamic vertex array
8794 // this is how a divisor of vertex influence on deformation
8795 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8796 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8797 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8798 // rsurface.batchvertex3f_vertexbuffer = NULL;
8799 // rsurface.batchvertex3f_bufferoffset = 0;
8800 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8801 // rsurface.batchnormal3f_vertexbuffer = NULL;
8802 // rsurface.batchnormal3f_bufferoffset = 0;
8803 for (j = 0;j < batchnumvertices;j++)
8805 // if the wavefunc depends on time, evaluate it per-vertex
8808 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8809 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8811 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8813 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8814 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8815 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8817 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8818 // rsurface.batchsvector3f_vertexbuffer = NULL;
8819 // rsurface.batchsvector3f_bufferoffset = 0;
8820 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8821 // rsurface.batchtvector3f_vertexbuffer = NULL;
8822 // rsurface.batchtvector3f_bufferoffset = 0;
8823 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);
8826 case Q3DEFORM_BULGE:
8827 // deform vertex array to make the surface have moving bulges
8828 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8829 // rsurface.batchvertex3f_vertexbuffer = NULL;
8830 // rsurface.batchvertex3f_bufferoffset = 0;
8831 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8832 // rsurface.batchnormal3f_vertexbuffer = NULL;
8833 // rsurface.batchnormal3f_bufferoffset = 0;
8834 for (j = 0;j < batchnumvertices;j++)
8836 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8837 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8839 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8840 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8841 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8843 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8844 // rsurface.batchsvector3f_vertexbuffer = NULL;
8845 // rsurface.batchsvector3f_bufferoffset = 0;
8846 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8847 // rsurface.batchtvector3f_vertexbuffer = NULL;
8848 // rsurface.batchtvector3f_bufferoffset = 0;
8849 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);
8853 // deform vertex array
8854 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8855 break; // if wavefunc is a nop, don't make a dynamic vertex array
8856 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8857 VectorScale(deform->parms, scale, waveparms);
8858 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8859 // rsurface.batchvertex3f_vertexbuffer = NULL;
8860 // rsurface.batchvertex3f_bufferoffset = 0;
8861 for (j = 0;j < batchnumvertices;j++)
8862 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8867 // generate texcoords based on the chosen texcoord source
8868 switch(rsurface.texture->tcgen.tcgen)
8871 case Q3TCGEN_TEXTURE:
8873 case Q3TCGEN_LIGHTMAP:
8874 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8875 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8876 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8877 if (rsurface.batchtexcoordlightmap2f)
8878 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8880 case Q3TCGEN_VECTOR:
8881 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8882 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8883 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8884 for (j = 0;j < batchnumvertices;j++)
8886 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8887 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8890 case Q3TCGEN_ENVIRONMENT:
8891 // make environment reflections using a spheremap
8892 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8893 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8894 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8895 for (j = 0;j < batchnumvertices;j++)
8897 // identical to Q3A's method, but executed in worldspace so
8898 // carried models can be shiny too
8900 float viewer[3], d, reflected[3], worldreflected[3];
8902 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8903 // VectorNormalize(viewer);
8905 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8907 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8908 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8909 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8910 // note: this is proportinal to viewer, so we can normalize later
8912 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8913 VectorNormalize(worldreflected);
8915 // note: this sphere map only uses world x and z!
8916 // so positive and negative y will LOOK THE SAME.
8917 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8918 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8922 // the only tcmod that needs software vertex processing is turbulent, so
8923 // check for it here and apply the changes if needed
8924 // and we only support that as the first one
8925 // (handling a mixture of turbulent and other tcmods would be problematic
8926 // without punting it entirely to a software path)
8927 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8929 amplitude = rsurface.texture->tcmods[0].parms[1];
8930 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8931 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8932 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8933 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8934 for (j = 0;j < batchnumvertices;j++)
8936 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);
8937 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8941 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8943 // convert the modified arrays to vertex structs
8944 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8945 // rsurface.batchvertexmeshbuffer = NULL;
8946 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8947 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8948 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8949 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8950 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8951 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
8952 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
8954 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8956 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
8957 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
8960 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
8961 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8962 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
8963 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
8964 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8965 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
8966 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
8967 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8968 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
8972 void RSurf_DrawBatch(void)
8974 // sometimes a zero triangle surface (usually a degenerate patch) makes it
8975 // through the pipeline, killing it earlier in the pipeline would have
8976 // per-surface overhead rather than per-batch overhead, so it's best to
8977 // reject it here, before it hits glDraw.
8978 if (rsurface.batchnumtriangles == 0)
8981 // batch debugging code
8982 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
8988 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
8989 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
8992 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
8994 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
8996 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
8997 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);
9004 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);
9007 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9009 // pick the closest matching water plane
9010 int planeindex, vertexindex, bestplaneindex = -1;
9014 r_waterstate_waterplane_t *p;
9015 qboolean prepared = false;
9017 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9019 if(p->camera_entity != rsurface.texture->camera_entity)
9024 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9026 if(rsurface.batchnumvertices == 0)
9029 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9031 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9032 d += fabs(PlaneDiff(vert, &p->plane));
9034 if (bestd > d || bestplaneindex < 0)
9037 bestplaneindex = planeindex;
9040 return bestplaneindex;
9041 // NOTE: this MAY return a totally unrelated water plane; we can ignore
9042 // this situation though, as it might be better to render single larger
9043 // batches with useless stuff (backface culled for example) than to
9044 // render multiple smaller batches
9047 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9050 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9051 rsurface.passcolor4f_vertexbuffer = 0;
9052 rsurface.passcolor4f_bufferoffset = 0;
9053 for (i = 0;i < rsurface.batchnumvertices;i++)
9054 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9057 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9064 if (rsurface.passcolor4f)
9066 // generate color arrays
9067 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9068 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9069 rsurface.passcolor4f_vertexbuffer = 0;
9070 rsurface.passcolor4f_bufferoffset = 0;
9071 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)
9073 f = RSurf_FogVertex(v);
9082 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9083 rsurface.passcolor4f_vertexbuffer = 0;
9084 rsurface.passcolor4f_bufferoffset = 0;
9085 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9087 f = RSurf_FogVertex(v);
9096 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9103 if (!rsurface.passcolor4f)
9105 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9106 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9107 rsurface.passcolor4f_vertexbuffer = 0;
9108 rsurface.passcolor4f_bufferoffset = 0;
9109 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)
9111 f = RSurf_FogVertex(v);
9112 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9113 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9114 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9119 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9124 if (!rsurface.passcolor4f)
9126 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9127 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9128 rsurface.passcolor4f_vertexbuffer = 0;
9129 rsurface.passcolor4f_bufferoffset = 0;
9130 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9139 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9144 if (!rsurface.passcolor4f)
9146 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9147 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9148 rsurface.passcolor4f_vertexbuffer = 0;
9149 rsurface.passcolor4f_bufferoffset = 0;
9150 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9152 c2[0] = c[0] + r_refdef.scene.ambient;
9153 c2[1] = c[1] + r_refdef.scene.ambient;
9154 c2[2] = c[2] + r_refdef.scene.ambient;
9159 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9162 rsurface.passcolor4f = NULL;
9163 rsurface.passcolor4f_vertexbuffer = 0;
9164 rsurface.passcolor4f_bufferoffset = 0;
9165 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9166 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9167 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9168 GL_Color(r, g, b, a);
9169 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9173 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9175 // TODO: optimize applyfog && applycolor case
9176 // just apply fog if necessary, and tint the fog color array if necessary
9177 rsurface.passcolor4f = NULL;
9178 rsurface.passcolor4f_vertexbuffer = 0;
9179 rsurface.passcolor4f_bufferoffset = 0;
9180 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9181 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9182 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9183 GL_Color(r, g, b, a);
9187 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9190 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9191 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9192 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9193 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9194 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9195 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9196 GL_Color(r, g, b, a);
9200 static void RSurf_DrawBatch_GL11_ClampColor(void)
9205 if (!rsurface.passcolor4f)
9207 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9209 c2[0] = bound(0.0f, c1[0], 1.0f);
9210 c2[1] = bound(0.0f, c1[1], 1.0f);
9211 c2[2] = bound(0.0f, c1[2], 1.0f);
9212 c2[3] = bound(0.0f, c1[3], 1.0f);
9216 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9226 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9227 rsurface.passcolor4f_vertexbuffer = 0;
9228 rsurface.passcolor4f_bufferoffset = 0;
9229 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)
9231 f = -DotProduct(r_refdef.view.forward, n);
9233 f = f * 0.85 + 0.15; // work around so stuff won't get black
9234 f *= r_refdef.lightmapintensity;
9235 Vector4Set(c, f, f, f, 1);
9239 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9241 RSurf_DrawBatch_GL11_ApplyFakeLight();
9242 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9243 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9244 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9245 GL_Color(r, g, b, a);
9249 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9257 vec3_t ambientcolor;
9258 vec3_t diffusecolor;
9262 VectorCopy(rsurface.modellight_lightdir, lightdir);
9263 f = 0.5f * r_refdef.lightmapintensity;
9264 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9265 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9266 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9267 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9268 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9269 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9271 if (VectorLength2(diffusecolor) > 0)
9273 // q3-style directional shading
9274 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9275 rsurface.passcolor4f_vertexbuffer = 0;
9276 rsurface.passcolor4f_bufferoffset = 0;
9277 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)
9279 if ((f = DotProduct(n, lightdir)) > 0)
9280 VectorMA(ambientcolor, f, diffusecolor, c);
9282 VectorCopy(ambientcolor, c);
9289 *applycolor = false;
9293 *r = ambientcolor[0];
9294 *g = ambientcolor[1];
9295 *b = ambientcolor[2];
9296 rsurface.passcolor4f = NULL;
9297 rsurface.passcolor4f_vertexbuffer = 0;
9298 rsurface.passcolor4f_bufferoffset = 0;
9302 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9304 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9305 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9306 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9307 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9308 GL_Color(r, g, b, a);
9312 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9320 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9321 rsurface.passcolor4f_vertexbuffer = 0;
9322 rsurface.passcolor4f_bufferoffset = 0;
9324 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9326 f = 1 - RSurf_FogVertex(v);
9334 void RSurf_SetupDepthAndCulling(void)
9336 // submodels are biased to avoid z-fighting with world surfaces that they
9337 // may be exactly overlapping (avoids z-fighting artifacts on certain
9338 // doors and things in Quake maps)
9339 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9340 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9341 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9342 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9345 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9347 // transparent sky would be ridiculous
9348 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9350 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9351 skyrenderlater = true;
9352 RSurf_SetupDepthAndCulling();
9354 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9355 // skymasking on them, and Quake3 never did sky masking (unlike
9356 // software Quake and software Quake2), so disable the sky masking
9357 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9358 // and skymasking also looks very bad when noclipping outside the
9359 // level, so don't use it then either.
9360 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9362 R_Mesh_ResetTextureState();
9363 if (skyrendermasked)
9365 R_SetupShader_DepthOrShadow();
9366 // depth-only (masking)
9367 GL_ColorMask(0,0,0,0);
9368 // just to make sure that braindead drivers don't draw
9369 // anything despite that colormask...
9370 GL_BlendFunc(GL_ZERO, GL_ONE);
9371 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9372 if (rsurface.batchvertex3fbuffer)
9373 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9375 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9379 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9381 GL_BlendFunc(GL_ONE, GL_ZERO);
9382 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9383 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9384 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9387 if (skyrendermasked)
9388 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9390 R_Mesh_ResetTextureState();
9391 GL_Color(1, 1, 1, 1);
9394 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9395 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9396 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9398 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9402 // render screenspace normalmap to texture
9404 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9409 // bind lightmap texture
9411 // water/refraction/reflection/camera surfaces have to be handled specially
9412 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9414 int start, end, startplaneindex;
9415 for (start = 0;start < texturenumsurfaces;start = end)
9417 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9418 if(startplaneindex < 0)
9420 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9421 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9425 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9427 // now that we have a batch using the same planeindex, render it
9428 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9430 // render water or distortion background
9432 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));
9434 // blend surface on top
9435 GL_DepthMask(false);
9436 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9439 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9441 // render surface with reflection texture as input
9442 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9443 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));
9450 // render surface batch normally
9451 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9452 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9456 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9458 // OpenGL 1.3 path - anything not completely ancient
9459 qboolean applycolor;
9462 const texturelayer_t *layer;
9463 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);
9464 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9466 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9469 int layertexrgbscale;
9470 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9472 if (layerindex == 0)
9476 GL_AlphaTest(false);
9477 GL_DepthFunc(GL_EQUAL);
9480 GL_DepthMask(layer->depthmask && writedepth);
9481 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9482 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9484 layertexrgbscale = 4;
9485 VectorScale(layer->color, 0.25f, layercolor);
9487 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9489 layertexrgbscale = 2;
9490 VectorScale(layer->color, 0.5f, layercolor);
9494 layertexrgbscale = 1;
9495 VectorScale(layer->color, 1.0f, layercolor);
9497 layercolor[3] = layer->color[3];
9498 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9499 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9500 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9501 switch (layer->type)
9503 case TEXTURELAYERTYPE_LITTEXTURE:
9504 // single-pass lightmapped texture with 2x rgbscale
9505 R_Mesh_TexBind(0, r_texture_white);
9506 R_Mesh_TexMatrix(0, NULL);
9507 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9508 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9509 R_Mesh_TexBind(1, layer->texture);
9510 R_Mesh_TexMatrix(1, &layer->texmatrix);
9511 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9512 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9513 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9514 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9515 else if (FAKELIGHT_ENABLED)
9516 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9517 else if (rsurface.uselightmaptexture)
9518 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9520 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9522 case TEXTURELAYERTYPE_TEXTURE:
9523 // singletexture unlit texture with transparency support
9524 R_Mesh_TexBind(0, layer->texture);
9525 R_Mesh_TexMatrix(0, &layer->texmatrix);
9526 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9527 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9528 R_Mesh_TexBind(1, 0);
9529 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9530 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9532 case TEXTURELAYERTYPE_FOG:
9533 // singletexture fogging
9536 R_Mesh_TexBind(0, layer->texture);
9537 R_Mesh_TexMatrix(0, &layer->texmatrix);
9538 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9539 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9543 R_Mesh_TexBind(0, 0);
9544 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9546 R_Mesh_TexBind(1, 0);
9547 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9548 // generate a color array for the fog pass
9549 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9550 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9554 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9557 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9559 GL_DepthFunc(GL_LEQUAL);
9560 GL_AlphaTest(false);
9564 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9566 // OpenGL 1.1 - crusty old voodoo path
9569 const texturelayer_t *layer;
9570 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);
9571 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9573 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9575 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9577 if (layerindex == 0)
9581 GL_AlphaTest(false);
9582 GL_DepthFunc(GL_EQUAL);
9585 GL_DepthMask(layer->depthmask && writedepth);
9586 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9587 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9588 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9589 switch (layer->type)
9591 case TEXTURELAYERTYPE_LITTEXTURE:
9592 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9594 // two-pass lit texture with 2x rgbscale
9595 // first the lightmap pass
9596 R_Mesh_TexBind(0, r_texture_white);
9597 R_Mesh_TexMatrix(0, NULL);
9598 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9599 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9600 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9601 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9602 else if (FAKELIGHT_ENABLED)
9603 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9604 else if (rsurface.uselightmaptexture)
9605 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9607 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9608 // then apply the texture to it
9609 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9610 R_Mesh_TexBind(0, layer->texture);
9611 R_Mesh_TexMatrix(0, &layer->texmatrix);
9612 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9613 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9614 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);
9618 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9619 R_Mesh_TexBind(0, layer->texture);
9620 R_Mesh_TexMatrix(0, &layer->texmatrix);
9621 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9622 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9623 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9624 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);
9626 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);
9629 case TEXTURELAYERTYPE_TEXTURE:
9630 // singletexture unlit texture with transparency support
9631 R_Mesh_TexBind(0, layer->texture);
9632 R_Mesh_TexMatrix(0, &layer->texmatrix);
9633 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9634 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9635 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);
9637 case TEXTURELAYERTYPE_FOG:
9638 // singletexture fogging
9641 R_Mesh_TexBind(0, layer->texture);
9642 R_Mesh_TexMatrix(0, &layer->texmatrix);
9643 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9644 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9648 R_Mesh_TexBind(0, 0);
9649 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9651 // generate a color array for the fog pass
9652 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9653 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9657 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9660 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9662 GL_DepthFunc(GL_LEQUAL);
9663 GL_AlphaTest(false);
9667 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9671 r_vertexgeneric_t *batchvertex;
9674 // R_Mesh_ResetTextureState();
9675 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9677 if(rsurface.texture && rsurface.texture->currentskinframe)
9679 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9680 c[3] *= rsurface.texture->currentalpha;
9690 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9692 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9693 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9694 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9697 // brighten it up (as texture value 127 means "unlit")
9698 c[0] *= 2 * r_refdef.view.colorscale;
9699 c[1] *= 2 * r_refdef.view.colorscale;
9700 c[2] *= 2 * r_refdef.view.colorscale;
9702 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9703 c[3] *= r_wateralpha.value;
9705 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9707 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9708 GL_DepthMask(false);
9710 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9712 GL_BlendFunc(GL_ONE, GL_ONE);
9713 GL_DepthMask(false);
9715 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9717 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9718 GL_DepthMask(false);
9720 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9722 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9723 GL_DepthMask(false);
9727 GL_BlendFunc(GL_ONE, GL_ZERO);
9728 GL_DepthMask(writedepth);
9731 if (r_showsurfaces.integer == 3)
9733 rsurface.passcolor4f = NULL;
9735 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9737 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9739 rsurface.passcolor4f = NULL;
9740 rsurface.passcolor4f_vertexbuffer = 0;
9741 rsurface.passcolor4f_bufferoffset = 0;
9743 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9745 qboolean applycolor = true;
9748 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9750 r_refdef.lightmapintensity = 1;
9751 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9752 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9754 else if (FAKELIGHT_ENABLED)
9756 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9758 r_refdef.lightmapintensity = r_fakelight_intensity.value;
9759 RSurf_DrawBatch_GL11_ApplyFakeLight();
9760 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9764 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9766 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9767 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9768 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9771 if(!rsurface.passcolor4f)
9772 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9774 RSurf_DrawBatch_GL11_ApplyAmbient();
9775 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9776 if(r_refdef.fogenabled)
9777 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9778 RSurf_DrawBatch_GL11_ClampColor();
9780 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9781 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9784 else if (!r_refdef.view.showdebug)
9786 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9787 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9788 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9790 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9791 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9793 R_Mesh_PrepareVertices_Generic_Unlock();
9796 else if (r_showsurfaces.integer == 4)
9798 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9799 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9800 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9802 unsigned char c = (vi << 3) * (1.0f / 256.0f);
9803 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9804 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9806 R_Mesh_PrepareVertices_Generic_Unlock();
9809 else if (r_showsurfaces.integer == 2)
9812 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9813 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9814 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9816 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9817 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9818 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9819 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9820 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9821 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9822 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9824 R_Mesh_PrepareVertices_Generic_Unlock();
9825 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9829 int texturesurfaceindex;
9831 const msurface_t *surface;
9832 float surfacecolor4f[4];
9833 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9834 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9836 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9838 surface = texturesurfacelist[texturesurfaceindex];
9839 k = (int)(((size_t)surface) / sizeof(msurface_t));
9840 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9841 for (j = 0;j < surface->num_vertices;j++)
9843 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9844 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9848 R_Mesh_PrepareVertices_Generic_Unlock();
9853 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9856 RSurf_SetupDepthAndCulling();
9857 if (r_showsurfaces.integer)
9859 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9862 switch (vid.renderpath)
9864 case RENDERPATH_GL20:
9865 case RENDERPATH_D3D9:
9866 case RENDERPATH_D3D10:
9867 case RENDERPATH_D3D11:
9868 case RENDERPATH_SOFT:
9869 case RENDERPATH_GLES2:
9870 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9872 case RENDERPATH_GL13:
9873 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9875 case RENDERPATH_GL11:
9876 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9882 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9885 RSurf_SetupDepthAndCulling();
9886 if (r_showsurfaces.integer)
9888 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9891 switch (vid.renderpath)
9893 case RENDERPATH_GL20:
9894 case RENDERPATH_D3D9:
9895 case RENDERPATH_D3D10:
9896 case RENDERPATH_D3D11:
9897 case RENDERPATH_SOFT:
9898 case RENDERPATH_GLES2:
9899 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9901 case RENDERPATH_GL13:
9902 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9904 case RENDERPATH_GL11:
9905 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9911 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9914 int texturenumsurfaces, endsurface;
9916 const msurface_t *surface;
9917 #define MAXBATCH_TRANSPARENTSURFACES 256
9918 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9920 // if the model is static it doesn't matter what value we give for
9921 // wantnormals and wanttangents, so this logic uses only rules applicable
9922 // to a model, knowing that they are meaningless otherwise
9923 if (ent == r_refdef.scene.worldentity)
9924 RSurf_ActiveWorldEntity();
9925 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9926 RSurf_ActiveModelEntity(ent, false, false, false);
9929 switch (vid.renderpath)
9931 case RENDERPATH_GL20:
9932 case RENDERPATH_D3D9:
9933 case RENDERPATH_D3D10:
9934 case RENDERPATH_D3D11:
9935 case RENDERPATH_SOFT:
9936 case RENDERPATH_GLES2:
9937 RSurf_ActiveModelEntity(ent, true, true, false);
9939 case RENDERPATH_GL13:
9940 case RENDERPATH_GL11:
9941 RSurf_ActiveModelEntity(ent, true, false, false);
9946 if (r_transparentdepthmasking.integer)
9948 qboolean setup = false;
9949 for (i = 0;i < numsurfaces;i = j)
9952 surface = rsurface.modelsurfaces + surfacelist[i];
9953 texture = surface->texture;
9954 rsurface.texture = R_GetCurrentTexture(texture);
9955 rsurface.lightmaptexture = NULL;
9956 rsurface.deluxemaptexture = NULL;
9957 rsurface.uselightmaptexture = false;
9958 // scan ahead until we find a different texture
9959 endsurface = min(i + 1024, numsurfaces);
9960 texturenumsurfaces = 0;
9961 texturesurfacelist[texturenumsurfaces++] = surface;
9962 for (;j < endsurface;j++)
9964 surface = rsurface.modelsurfaces + surfacelist[j];
9965 if (texture != surface->texture)
9967 texturesurfacelist[texturenumsurfaces++] = surface;
9969 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9971 // render the range of surfaces as depth
9975 GL_ColorMask(0,0,0,0);
9978 GL_BlendFunc(GL_ONE, GL_ZERO);
9980 // R_Mesh_ResetTextureState();
9981 R_SetupShader_DepthOrShadow();
9983 RSurf_SetupDepthAndCulling();
9984 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9985 if (rsurface.batchvertex3fbuffer)
9986 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9988 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9992 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9995 for (i = 0;i < numsurfaces;i = j)
9998 surface = rsurface.modelsurfaces + surfacelist[i];
9999 texture = surface->texture;
10000 rsurface.texture = R_GetCurrentTexture(texture);
10001 // scan ahead until we find a different texture
10002 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
10003 texturenumsurfaces = 0;
10004 texturesurfacelist[texturenumsurfaces++] = surface;
10005 if(FAKELIGHT_ENABLED)
10007 rsurface.lightmaptexture = NULL;
10008 rsurface.deluxemaptexture = NULL;
10009 rsurface.uselightmaptexture = false;
10010 for (;j < endsurface;j++)
10012 surface = rsurface.modelsurfaces + surfacelist[j];
10013 if (texture != surface->texture)
10015 texturesurfacelist[texturenumsurfaces++] = surface;
10020 rsurface.lightmaptexture = surface->lightmaptexture;
10021 rsurface.deluxemaptexture = surface->deluxemaptexture;
10022 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10023 for (;j < endsurface;j++)
10025 surface = rsurface.modelsurfaces + surfacelist[j];
10026 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10028 texturesurfacelist[texturenumsurfaces++] = surface;
10031 // render the range of surfaces
10032 if (ent == r_refdef.scene.worldentity)
10033 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10035 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10037 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10040 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10042 // transparent surfaces get pushed off into the transparent queue
10043 int surfacelistindex;
10044 const msurface_t *surface;
10045 vec3_t tempcenter, center;
10046 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10048 surface = texturesurfacelist[surfacelistindex];
10049 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10050 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10051 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10052 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10053 if (queueentity->transparent_offset) // transparent offset
10055 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10056 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10057 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10059 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10063 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10065 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10067 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10069 RSurf_SetupDepthAndCulling();
10070 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10071 if (rsurface.batchvertex3fbuffer)
10072 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10074 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10078 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10080 const entity_render_t *queueentity = r_refdef.scene.worldentity;
10083 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10086 if (!rsurface.texture->currentnumlayers)
10088 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10089 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10091 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10093 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10094 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10095 else if (!rsurface.texture->currentnumlayers)
10097 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10099 // in the deferred case, transparent surfaces were queued during prepass
10100 if (!r_shadow_usingdeferredprepass)
10101 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10105 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10106 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10111 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10114 texture_t *texture;
10115 R_FrameData_SetMark();
10116 // break the surface list down into batches by texture and use of lightmapping
10117 for (i = 0;i < numsurfaces;i = j)
10120 // texture is the base texture pointer, rsurface.texture is the
10121 // current frame/skin the texture is directing us to use (for example
10122 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10123 // use skin 1 instead)
10124 texture = surfacelist[i]->texture;
10125 rsurface.texture = R_GetCurrentTexture(texture);
10126 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10128 // if this texture is not the kind we want, skip ahead to the next one
10129 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10133 if(FAKELIGHT_ENABLED || depthonly || prepass)
10135 rsurface.lightmaptexture = NULL;
10136 rsurface.deluxemaptexture = NULL;
10137 rsurface.uselightmaptexture = false;
10138 // simply scan ahead until we find a different texture or lightmap state
10139 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10144 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10145 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10146 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10147 // simply scan ahead until we find a different texture or lightmap state
10148 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10151 // render the range of surfaces
10152 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10154 R_FrameData_ReturnToMark();
10157 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10161 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10164 if (!rsurface.texture->currentnumlayers)
10166 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10167 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10169 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10171 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10172 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10173 else if (!rsurface.texture->currentnumlayers)
10175 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10177 // in the deferred case, transparent surfaces were queued during prepass
10178 if (!r_shadow_usingdeferredprepass)
10179 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10183 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10184 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10189 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10192 texture_t *texture;
10193 R_FrameData_SetMark();
10194 // break the surface list down into batches by texture and use of lightmapping
10195 for (i = 0;i < numsurfaces;i = j)
10198 // texture is the base texture pointer, rsurface.texture is the
10199 // current frame/skin the texture is directing us to use (for example
10200 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10201 // use skin 1 instead)
10202 texture = surfacelist[i]->texture;
10203 rsurface.texture = R_GetCurrentTexture(texture);
10204 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10206 // if this texture is not the kind we want, skip ahead to the next one
10207 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10211 if(FAKELIGHT_ENABLED || depthonly || prepass)
10213 rsurface.lightmaptexture = NULL;
10214 rsurface.deluxemaptexture = NULL;
10215 rsurface.uselightmaptexture = false;
10216 // simply scan ahead until we find a different texture or lightmap state
10217 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10222 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10223 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10224 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10225 // simply scan ahead until we find a different texture or lightmap state
10226 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10229 // render the range of surfaces
10230 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10232 R_FrameData_ReturnToMark();
10235 float locboxvertex3f[6*4*3] =
10237 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10238 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10239 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10240 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10241 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10242 1,0,0, 0,0,0, 0,1,0, 1,1,0
10245 unsigned short locboxelements[6*2*3] =
10250 12,13,14, 12,14,15,
10251 16,17,18, 16,18,19,
10255 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10258 cl_locnode_t *loc = (cl_locnode_t *)ent;
10260 float vertex3f[6*4*3];
10262 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10263 GL_DepthMask(false);
10264 GL_DepthRange(0, 1);
10265 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10266 GL_DepthTest(true);
10267 GL_CullFace(GL_NONE);
10268 R_EntityMatrix(&identitymatrix);
10270 // R_Mesh_ResetTextureState();
10272 i = surfacelist[0];
10273 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10274 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10275 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10276 surfacelist[0] < 0 ? 0.5f : 0.125f);
10278 if (VectorCompare(loc->mins, loc->maxs))
10280 VectorSet(size, 2, 2, 2);
10281 VectorMA(loc->mins, -0.5f, size, mins);
10285 VectorCopy(loc->mins, mins);
10286 VectorSubtract(loc->maxs, loc->mins, size);
10289 for (i = 0;i < 6*4*3;)
10290 for (j = 0;j < 3;j++, i++)
10291 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10293 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10294 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10295 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10298 void R_DrawLocs(void)
10301 cl_locnode_t *loc, *nearestloc;
10303 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10304 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10306 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10307 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10311 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10313 if (decalsystem->decals)
10314 Mem_Free(decalsystem->decals);
10315 memset(decalsystem, 0, sizeof(*decalsystem));
10318 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)
10321 tridecal_t *decals;
10324 // expand or initialize the system
10325 if (decalsystem->maxdecals <= decalsystem->numdecals)
10327 decalsystem_t old = *decalsystem;
10328 qboolean useshortelements;
10329 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10330 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10331 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)));
10332 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10333 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10334 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10335 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10336 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10337 if (decalsystem->numdecals)
10338 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10340 Mem_Free(old.decals);
10341 for (i = 0;i < decalsystem->maxdecals*3;i++)
10342 decalsystem->element3i[i] = i;
10343 if (useshortelements)
10344 for (i = 0;i < decalsystem->maxdecals*3;i++)
10345 decalsystem->element3s[i] = i;
10348 // grab a decal and search for another free slot for the next one
10349 decals = decalsystem->decals;
10350 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10351 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10353 decalsystem->freedecal = i;
10354 if (decalsystem->numdecals <= i)
10355 decalsystem->numdecals = i + 1;
10357 // initialize the decal
10359 decal->triangleindex = triangleindex;
10360 decal->surfaceindex = surfaceindex;
10361 decal->decalsequence = decalsequence;
10362 decal->color4f[0][0] = c0[0];
10363 decal->color4f[0][1] = c0[1];
10364 decal->color4f[0][2] = c0[2];
10365 decal->color4f[0][3] = 1;
10366 decal->color4f[1][0] = c1[0];
10367 decal->color4f[1][1] = c1[1];
10368 decal->color4f[1][2] = c1[2];
10369 decal->color4f[1][3] = 1;
10370 decal->color4f[2][0] = c2[0];
10371 decal->color4f[2][1] = c2[1];
10372 decal->color4f[2][2] = c2[2];
10373 decal->color4f[2][3] = 1;
10374 decal->vertex3f[0][0] = v0[0];
10375 decal->vertex3f[0][1] = v0[1];
10376 decal->vertex3f[0][2] = v0[2];
10377 decal->vertex3f[1][0] = v1[0];
10378 decal->vertex3f[1][1] = v1[1];
10379 decal->vertex3f[1][2] = v1[2];
10380 decal->vertex3f[2][0] = v2[0];
10381 decal->vertex3f[2][1] = v2[1];
10382 decal->vertex3f[2][2] = v2[2];
10383 decal->texcoord2f[0][0] = t0[0];
10384 decal->texcoord2f[0][1] = t0[1];
10385 decal->texcoord2f[1][0] = t1[0];
10386 decal->texcoord2f[1][1] = t1[1];
10387 decal->texcoord2f[2][0] = t2[0];
10388 decal->texcoord2f[2][1] = t2[1];
10389 TriangleNormal(v0, v1, v2, decal->plane);
10390 VectorNormalize(decal->plane);
10391 decal->plane[3] = DotProduct(v0, decal->plane);
10394 extern cvar_t cl_decals_bias;
10395 extern cvar_t cl_decals_models;
10396 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10397 // baseparms, parms, temps
10398 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)
10403 const float *vertex3f;
10404 const float *normal3f;
10406 float points[2][9][3];
10413 e = rsurface.modelelement3i + 3*triangleindex;
10415 vertex3f = rsurface.modelvertex3f;
10416 normal3f = rsurface.modelnormal3f;
10420 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10422 index = 3*e[cornerindex];
10423 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10428 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10430 index = 3*e[cornerindex];
10431 VectorCopy(vertex3f + index, v[cornerindex]);
10436 //TriangleNormal(v[0], v[1], v[2], normal);
10437 //if (DotProduct(normal, localnormal) < 0.0f)
10439 // clip by each of the box planes formed from the projection matrix
10440 // if anything survives, we emit the decal
10441 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]);
10444 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]);
10447 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]);
10450 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]);
10453 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]);
10456 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]);
10459 // some part of the triangle survived, so we have to accept it...
10462 // dynamic always uses the original triangle
10464 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10466 index = 3*e[cornerindex];
10467 VectorCopy(vertex3f + index, v[cornerindex]);
10470 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10472 // convert vertex positions to texcoords
10473 Matrix4x4_Transform(projection, v[cornerindex], temp);
10474 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10475 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10476 // calculate distance fade from the projection origin
10477 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10478 f = bound(0.0f, f, 1.0f);
10479 c[cornerindex][0] = r * f;
10480 c[cornerindex][1] = g * f;
10481 c[cornerindex][2] = b * f;
10482 c[cornerindex][3] = 1.0f;
10483 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10486 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);
10488 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10489 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);
10491 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)
10493 matrix4x4_t projection;
10494 decalsystem_t *decalsystem;
10497 const msurface_t *surface;
10498 const msurface_t *surfaces;
10499 const int *surfacelist;
10500 const texture_t *texture;
10502 int numsurfacelist;
10503 int surfacelistindex;
10506 float localorigin[3];
10507 float localnormal[3];
10508 float localmins[3];
10509 float localmaxs[3];
10512 float planes[6][4];
10515 int bih_triangles_count;
10516 int bih_triangles[256];
10517 int bih_surfaces[256];
10519 decalsystem = &ent->decalsystem;
10520 model = ent->model;
10521 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10523 R_DecalSystem_Reset(&ent->decalsystem);
10527 if (!model->brush.data_leafs && !cl_decals_models.integer)
10529 if (decalsystem->model)
10530 R_DecalSystem_Reset(decalsystem);
10534 if (decalsystem->model != model)
10535 R_DecalSystem_Reset(decalsystem);
10536 decalsystem->model = model;
10538 RSurf_ActiveModelEntity(ent, true, false, false);
10540 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10541 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10542 VectorNormalize(localnormal);
10543 localsize = worldsize*rsurface.inversematrixscale;
10544 localmins[0] = localorigin[0] - localsize;
10545 localmins[1] = localorigin[1] - localsize;
10546 localmins[2] = localorigin[2] - localsize;
10547 localmaxs[0] = localorigin[0] + localsize;
10548 localmaxs[1] = localorigin[1] + localsize;
10549 localmaxs[2] = localorigin[2] + localsize;
10551 //VectorCopy(localnormal, planes[4]);
10552 //VectorVectors(planes[4], planes[2], planes[0]);
10553 AnglesFromVectors(angles, localnormal, NULL, false);
10554 AngleVectors(angles, planes[0], planes[2], planes[4]);
10555 VectorNegate(planes[0], planes[1]);
10556 VectorNegate(planes[2], planes[3]);
10557 VectorNegate(planes[4], planes[5]);
10558 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10559 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10560 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10561 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10562 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10563 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10568 matrix4x4_t forwardprojection;
10569 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10570 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10575 float projectionvector[4][3];
10576 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10577 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10578 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10579 projectionvector[0][0] = planes[0][0] * ilocalsize;
10580 projectionvector[0][1] = planes[1][0] * ilocalsize;
10581 projectionvector[0][2] = planes[2][0] * ilocalsize;
10582 projectionvector[1][0] = planes[0][1] * ilocalsize;
10583 projectionvector[1][1] = planes[1][1] * ilocalsize;
10584 projectionvector[1][2] = planes[2][1] * ilocalsize;
10585 projectionvector[2][0] = planes[0][2] * ilocalsize;
10586 projectionvector[2][1] = planes[1][2] * ilocalsize;
10587 projectionvector[2][2] = planes[2][2] * ilocalsize;
10588 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10589 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10590 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10591 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10595 dynamic = model->surfmesh.isanimated;
10596 numsurfacelist = model->nummodelsurfaces;
10597 surfacelist = model->sortedmodelsurfaces;
10598 surfaces = model->data_surfaces;
10601 bih_triangles_count = -1;
10604 if(model->render_bih.numleafs)
10605 bih = &model->render_bih;
10606 else if(model->collision_bih.numleafs)
10607 bih = &model->collision_bih;
10610 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10611 if(bih_triangles_count == 0)
10613 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10615 if(bih_triangles_count > 0)
10617 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10619 surfaceindex = bih_surfaces[triangleindex];
10620 surface = surfaces + surfaceindex;
10621 texture = surface->texture;
10622 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10624 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10626 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10631 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10633 surfaceindex = surfacelist[surfacelistindex];
10634 surface = surfaces + surfaceindex;
10635 // check cull box first because it rejects more than any other check
10636 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10638 // skip transparent surfaces
10639 texture = surface->texture;
10640 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10642 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10644 numtriangles = surface->num_triangles;
10645 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10646 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10651 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10652 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)
10654 int renderentityindex;
10655 float worldmins[3];
10656 float worldmaxs[3];
10657 entity_render_t *ent;
10659 if (!cl_decals_newsystem.integer)
10662 worldmins[0] = worldorigin[0] - worldsize;
10663 worldmins[1] = worldorigin[1] - worldsize;
10664 worldmins[2] = worldorigin[2] - worldsize;
10665 worldmaxs[0] = worldorigin[0] + worldsize;
10666 worldmaxs[1] = worldorigin[1] + worldsize;
10667 worldmaxs[2] = worldorigin[2] + worldsize;
10669 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10671 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10673 ent = r_refdef.scene.entities[renderentityindex];
10674 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10677 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10681 typedef struct r_decalsystem_splatqueue_s
10683 vec3_t worldorigin;
10684 vec3_t worldnormal;
10690 r_decalsystem_splatqueue_t;
10692 int r_decalsystem_numqueued = 0;
10693 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10695 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)
10697 r_decalsystem_splatqueue_t *queue;
10699 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10702 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10703 VectorCopy(worldorigin, queue->worldorigin);
10704 VectorCopy(worldnormal, queue->worldnormal);
10705 Vector4Set(queue->color, r, g, b, a);
10706 Vector4Set(queue->tcrange, s1, t1, s2, t2);
10707 queue->worldsize = worldsize;
10708 queue->decalsequence = cl.decalsequence++;
10711 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10714 r_decalsystem_splatqueue_t *queue;
10716 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10717 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);
10718 r_decalsystem_numqueued = 0;
10721 extern cvar_t cl_decals_max;
10722 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10725 decalsystem_t *decalsystem = &ent->decalsystem;
10732 if (!decalsystem->numdecals)
10735 if (r_showsurfaces.integer)
10738 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10740 R_DecalSystem_Reset(decalsystem);
10744 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10745 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10747 if (decalsystem->lastupdatetime)
10748 frametime = (cl.time - decalsystem->lastupdatetime);
10751 decalsystem->lastupdatetime = cl.time;
10752 decal = decalsystem->decals;
10753 numdecals = decalsystem->numdecals;
10755 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10757 if (decal->color4f[0][3])
10759 decal->lived += frametime;
10760 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10762 memset(decal, 0, sizeof(*decal));
10763 if (decalsystem->freedecal > i)
10764 decalsystem->freedecal = i;
10768 decal = decalsystem->decals;
10769 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10772 // collapse the array by shuffling the tail decals into the gaps
10775 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10776 decalsystem->freedecal++;
10777 if (decalsystem->freedecal == numdecals)
10779 decal[decalsystem->freedecal] = decal[--numdecals];
10782 decalsystem->numdecals = numdecals;
10784 if (numdecals <= 0)
10786 // if there are no decals left, reset decalsystem
10787 R_DecalSystem_Reset(decalsystem);
10791 extern skinframe_t *decalskinframe;
10792 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10795 decalsystem_t *decalsystem = &ent->decalsystem;
10804 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10807 numdecals = decalsystem->numdecals;
10811 if (r_showsurfaces.integer)
10814 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10816 R_DecalSystem_Reset(decalsystem);
10820 // if the model is static it doesn't matter what value we give for
10821 // wantnormals and wanttangents, so this logic uses only rules applicable
10822 // to a model, knowing that they are meaningless otherwise
10823 if (ent == r_refdef.scene.worldentity)
10824 RSurf_ActiveWorldEntity();
10826 RSurf_ActiveModelEntity(ent, false, false, false);
10828 decalsystem->lastupdatetime = cl.time;
10829 decal = decalsystem->decals;
10831 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10833 // update vertex positions for animated models
10834 v3f = decalsystem->vertex3f;
10835 c4f = decalsystem->color4f;
10836 t2f = decalsystem->texcoord2f;
10837 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10839 if (!decal->color4f[0][3])
10842 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10846 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
10849 // update color values for fading decals
10850 if (decal->lived >= cl_decals_time.value)
10851 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10855 c4f[ 0] = decal->color4f[0][0] * alpha;
10856 c4f[ 1] = decal->color4f[0][1] * alpha;
10857 c4f[ 2] = decal->color4f[0][2] * alpha;
10859 c4f[ 4] = decal->color4f[1][0] * alpha;
10860 c4f[ 5] = decal->color4f[1][1] * alpha;
10861 c4f[ 6] = decal->color4f[1][2] * alpha;
10863 c4f[ 8] = decal->color4f[2][0] * alpha;
10864 c4f[ 9] = decal->color4f[2][1] * alpha;
10865 c4f[10] = decal->color4f[2][2] * alpha;
10868 t2f[0] = decal->texcoord2f[0][0];
10869 t2f[1] = decal->texcoord2f[0][1];
10870 t2f[2] = decal->texcoord2f[1][0];
10871 t2f[3] = decal->texcoord2f[1][1];
10872 t2f[4] = decal->texcoord2f[2][0];
10873 t2f[5] = decal->texcoord2f[2][1];
10875 // update vertex positions for animated models
10876 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10878 e = rsurface.modelelement3i + 3*decal->triangleindex;
10879 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10880 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10881 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10885 VectorCopy(decal->vertex3f[0], v3f);
10886 VectorCopy(decal->vertex3f[1], v3f + 3);
10887 VectorCopy(decal->vertex3f[2], v3f + 6);
10890 if (r_refdef.fogenabled)
10892 alpha = RSurf_FogVertex(v3f);
10893 VectorScale(c4f, alpha, c4f);
10894 alpha = RSurf_FogVertex(v3f + 3);
10895 VectorScale(c4f + 4, alpha, c4f + 4);
10896 alpha = RSurf_FogVertex(v3f + 6);
10897 VectorScale(c4f + 8, alpha, c4f + 8);
10908 r_refdef.stats.drawndecals += numtris;
10910 // now render the decals all at once
10911 // (this assumes they all use one particle font texture!)
10912 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);
10913 // R_Mesh_ResetTextureState();
10914 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10915 GL_DepthMask(false);
10916 GL_DepthRange(0, 1);
10917 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10918 GL_DepthTest(true);
10919 GL_CullFace(GL_NONE);
10920 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10921 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10922 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10926 static void R_DrawModelDecals(void)
10930 // fade faster when there are too many decals
10931 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10932 for (i = 0;i < r_refdef.scene.numentities;i++)
10933 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10935 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10936 for (i = 0;i < r_refdef.scene.numentities;i++)
10937 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10938 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10940 R_DecalSystem_ApplySplatEntitiesQueue();
10942 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10943 for (i = 0;i < r_refdef.scene.numentities;i++)
10944 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10946 r_refdef.stats.totaldecals += numdecals;
10948 if (r_showsurfaces.integer)
10951 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10953 for (i = 0;i < r_refdef.scene.numentities;i++)
10955 if (!r_refdef.viewcache.entityvisible[i])
10957 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10958 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10962 extern cvar_t mod_collision_bih;
10963 void R_DrawDebugModel(void)
10965 entity_render_t *ent = rsurface.entity;
10966 int i, j, k, l, flagsmask;
10967 const msurface_t *surface;
10968 dp_model_t *model = ent->model;
10971 switch(vid.renderpath)
10973 case RENDERPATH_GL11:
10974 case RENDERPATH_GL13:
10975 case RENDERPATH_GL20:
10977 case RENDERPATH_D3D9:
10978 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10980 case RENDERPATH_D3D10:
10981 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10983 case RENDERPATH_D3D11:
10984 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10986 case RENDERPATH_SOFT:
10987 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10989 case RENDERPATH_GLES2:
10990 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10994 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
10996 // R_Mesh_ResetTextureState();
10997 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10998 GL_DepthRange(0, 1);
10999 GL_DepthTest(!r_showdisabledepthtest.integer);
11000 GL_DepthMask(false);
11001 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11003 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11007 qboolean cullbox = ent == r_refdef.scene.worldentity;
11008 const q3mbrush_t *brush;
11009 const bih_t *bih = &model->collision_bih;
11010 const bih_leaf_t *bihleaf;
11011 float vertex3f[3][3];
11012 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11014 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11016 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11018 switch (bihleaf->type)
11021 brush = model->brush.data_brushes + bihleaf->itemindex;
11022 if (brush->colbrushf && brush->colbrushf->numtriangles)
11024 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);
11025 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11026 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11029 case BIH_COLLISIONTRIANGLE:
11030 triangleindex = bihleaf->itemindex;
11031 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11032 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11033 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11034 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);
11035 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11036 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11038 case BIH_RENDERTRIANGLE:
11039 triangleindex = bihleaf->itemindex;
11040 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11041 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11042 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11043 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);
11044 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11045 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11051 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11053 if (r_showtris.integer || (r_shownormals.value != 0))
11055 if (r_showdisabledepthtest.integer)
11057 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11058 GL_DepthMask(false);
11062 GL_BlendFunc(GL_ONE, GL_ZERO);
11063 GL_DepthMask(true);
11065 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11067 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11069 rsurface.texture = R_GetCurrentTexture(surface->texture);
11070 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11072 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11073 if (r_showtris.value > 0)
11075 if (!rsurface.texture->currentlayers->depthmask)
11076 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11077 else if (ent == r_refdef.scene.worldentity)
11078 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11080 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11081 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11082 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
11084 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
11087 if (r_shownormals.value < 0)
11089 qglBegin(GL_LINES);
11090 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11092 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11093 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11094 qglVertex3f(v[0], v[1], v[2]);
11095 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11096 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11097 qglVertex3f(v[0], v[1], v[2]);
11102 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11104 qglBegin(GL_LINES);
11105 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11107 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11108 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11109 qglVertex3f(v[0], v[1], v[2]);
11110 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11111 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11112 qglVertex3f(v[0], v[1], v[2]);
11116 qglBegin(GL_LINES);
11117 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11119 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11120 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11121 qglVertex3f(v[0], v[1], v[2]);
11122 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11123 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11124 qglVertex3f(v[0], v[1], v[2]);
11128 qglBegin(GL_LINES);
11129 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11131 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11132 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11133 qglVertex3f(v[0], v[1], v[2]);
11134 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11135 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11136 qglVertex3f(v[0], v[1], v[2]);
11143 rsurface.texture = NULL;
11147 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11148 int r_maxsurfacelist = 0;
11149 const msurface_t **r_surfacelist = NULL;
11150 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11152 int i, j, endj, flagsmask;
11153 dp_model_t *model = r_refdef.scene.worldmodel;
11154 msurface_t *surfaces;
11155 unsigned char *update;
11156 int numsurfacelist = 0;
11160 if (r_maxsurfacelist < model->num_surfaces)
11162 r_maxsurfacelist = model->num_surfaces;
11164 Mem_Free((msurface_t**)r_surfacelist);
11165 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11168 RSurf_ActiveWorldEntity();
11170 surfaces = model->data_surfaces;
11171 update = model->brushq1.lightmapupdateflags;
11173 // update light styles on this submodel
11174 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11176 model_brush_lightstyleinfo_t *style;
11177 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11179 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11181 int *list = style->surfacelist;
11182 style->value = r_refdef.scene.lightstylevalue[style->style];
11183 for (j = 0;j < style->numsurfaces;j++)
11184 update[list[j]] = true;
11189 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11193 R_DrawDebugModel();
11194 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11198 rsurface.lightmaptexture = NULL;
11199 rsurface.deluxemaptexture = NULL;
11200 rsurface.uselightmaptexture = false;
11201 rsurface.texture = NULL;
11202 rsurface.rtlight = NULL;
11203 numsurfacelist = 0;
11204 // add visible surfaces to draw list
11205 for (i = 0;i < model->nummodelsurfaces;i++)
11207 j = model->sortedmodelsurfaces[i];
11208 if (r_refdef.viewcache.world_surfacevisible[j])
11209 r_surfacelist[numsurfacelist++] = surfaces + j;
11211 // update lightmaps if needed
11212 if (model->brushq1.firstrender)
11214 model->brushq1.firstrender = false;
11215 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11217 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11221 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11222 if (r_refdef.viewcache.world_surfacevisible[j])
11224 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11226 // don't do anything if there were no surfaces
11227 if (!numsurfacelist)
11229 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11232 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11234 // add to stats if desired
11235 if (r_speeds.integer && !skysurfaces && !depthonly)
11237 r_refdef.stats.world_surfaces += numsurfacelist;
11238 for (j = 0;j < numsurfacelist;j++)
11239 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11242 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11245 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11247 int i, j, endj, flagsmask;
11248 dp_model_t *model = ent->model;
11249 msurface_t *surfaces;
11250 unsigned char *update;
11251 int numsurfacelist = 0;
11255 if (r_maxsurfacelist < model->num_surfaces)
11257 r_maxsurfacelist = model->num_surfaces;
11259 Mem_Free((msurface_t **)r_surfacelist);
11260 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11263 // if the model is static it doesn't matter what value we give for
11264 // wantnormals and wanttangents, so this logic uses only rules applicable
11265 // to a model, knowing that they are meaningless otherwise
11266 if (ent == r_refdef.scene.worldentity)
11267 RSurf_ActiveWorldEntity();
11268 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11269 RSurf_ActiveModelEntity(ent, false, false, false);
11271 RSurf_ActiveModelEntity(ent, true, true, true);
11272 else if (depthonly)
11274 switch (vid.renderpath)
11276 case RENDERPATH_GL20:
11277 case RENDERPATH_D3D9:
11278 case RENDERPATH_D3D10:
11279 case RENDERPATH_D3D11:
11280 case RENDERPATH_SOFT:
11281 case RENDERPATH_GLES2:
11282 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11284 case RENDERPATH_GL13:
11285 case RENDERPATH_GL11:
11286 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11292 switch (vid.renderpath)
11294 case RENDERPATH_GL20:
11295 case RENDERPATH_D3D9:
11296 case RENDERPATH_D3D10:
11297 case RENDERPATH_D3D11:
11298 case RENDERPATH_SOFT:
11299 case RENDERPATH_GLES2:
11300 RSurf_ActiveModelEntity(ent, true, true, false);
11302 case RENDERPATH_GL13:
11303 case RENDERPATH_GL11:
11304 RSurf_ActiveModelEntity(ent, true, false, false);
11309 surfaces = model->data_surfaces;
11310 update = model->brushq1.lightmapupdateflags;
11312 // update light styles
11313 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11315 model_brush_lightstyleinfo_t *style;
11316 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11318 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11320 int *list = style->surfacelist;
11321 style->value = r_refdef.scene.lightstylevalue[style->style];
11322 for (j = 0;j < style->numsurfaces;j++)
11323 update[list[j]] = true;
11328 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11332 R_DrawDebugModel();
11333 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11337 rsurface.lightmaptexture = NULL;
11338 rsurface.deluxemaptexture = NULL;
11339 rsurface.uselightmaptexture = false;
11340 rsurface.texture = NULL;
11341 rsurface.rtlight = NULL;
11342 numsurfacelist = 0;
11343 // add visible surfaces to draw list
11344 for (i = 0;i < model->nummodelsurfaces;i++)
11345 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11346 // don't do anything if there were no surfaces
11347 if (!numsurfacelist)
11349 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11352 // update lightmaps if needed
11356 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11361 R_BuildLightMap(ent, surfaces + j);
11366 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11368 R_BuildLightMap(ent, surfaces + j);
11369 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11371 // add to stats if desired
11372 if (r_speeds.integer && !skysurfaces && !depthonly)
11374 r_refdef.stats.entities_surfaces += numsurfacelist;
11375 for (j = 0;j < numsurfacelist;j++)
11376 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11379 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11382 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11384 static texture_t texture;
11385 static msurface_t surface;
11386 const msurface_t *surfacelist = &surface;
11388 // fake enough texture and surface state to render this geometry
11390 texture.update_lastrenderframe = -1; // regenerate this texture
11391 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11392 texture.currentskinframe = skinframe;
11393 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11394 texture.offsetmapping = OFFSETMAPPING_OFF;
11395 texture.offsetscale = 1;
11396 texture.specularscalemod = 1;
11397 texture.specularpowermod = 1;
11399 surface.texture = &texture;
11400 surface.num_triangles = numtriangles;
11401 surface.num_firsttriangle = firsttriangle;
11402 surface.num_vertices = numvertices;
11403 surface.num_firstvertex = firstvertex;
11406 rsurface.texture = R_GetCurrentTexture(surface.texture);
11407 rsurface.lightmaptexture = NULL;
11408 rsurface.deluxemaptexture = NULL;
11409 rsurface.uselightmaptexture = false;
11410 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11413 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)
11415 static msurface_t surface;
11416 const msurface_t *surfacelist = &surface;
11418 // fake enough texture and surface state to render this geometry
11419 surface.texture = texture;
11420 surface.num_triangles = numtriangles;
11421 surface.num_firsttriangle = firsttriangle;
11422 surface.num_vertices = numvertices;
11423 surface.num_firstvertex = firstvertex;
11426 rsurface.texture = R_GetCurrentTexture(surface.texture);
11427 rsurface.lightmaptexture = NULL;
11428 rsurface.deluxemaptexture = NULL;
11429 rsurface.uselightmaptexture = false;
11430 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);