2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "cl_dyntexture.h"
30 #include "dpsoftrast.h"
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
55 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
56 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
57 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
58 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
60 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
62 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
63 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
64 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
65 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
66 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
68 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
69 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
70 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
71 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
72 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
73 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
74 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
75 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
76 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
77 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
78 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
79 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
80 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
81 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
82 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
83 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
84 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
85 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
86 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
87 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
88 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
89 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
90 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
91 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
92 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
93 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
94 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
95 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
97 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
98 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
99 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
101 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
102 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
103 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
104 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
105 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
106 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
107 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
108 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
109 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
110 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
111 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
112 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
113 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
114 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
115 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
116 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
117 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
118 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
119 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
120 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
122 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
123 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
124 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
125 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
126 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
127 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
128 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
129 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
131 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
132 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
134 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
135 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
136 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
137 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
138 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
140 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
141 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
142 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
144 cvar_t r_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"};
145 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"};
146 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
147 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.25", "worst acceptable quality"};
148 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"};
149 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)"};
150 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)"};
151 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "90", "desired framerate"};
153 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)"};
154 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
155 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)"};
156 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
157 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)"};
158 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
159 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
160 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)"};
161 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)"};
162 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)"};
163 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)"};
164 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)"};
165 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)"};
166 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)"};
167 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)"};
169 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)"};
170 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
171 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"};
172 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
173 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
174 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
176 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
177 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
178 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
179 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
181 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
182 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
183 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
184 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
185 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
186 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
187 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
189 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
190 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
191 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
192 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)"};
193 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
194 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
195 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
196 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
197 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
198 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
200 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"};
202 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"};
204 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
206 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
207 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"};
208 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
209 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
210 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
211 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
212 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)"};
213 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
214 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
216 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
217 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"};
219 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."};
221 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)"};
223 extern cvar_t v_glslgamma;
225 extern qboolean v_flipped_state;
227 static struct r_bloomstate_s
232 int bloomwidth, bloomheight;
234 textype_t texturetype;
235 int viewfbo; // used to check if r_viewfbo cvar has changed
237 int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
238 rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
239 rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
241 int screentexturewidth, screentextureheight;
242 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
244 int bloomtexturewidth, bloomtextureheight;
245 rtexture_t *texture_bloom;
247 // arrays for rendering the screen passes
248 float screentexcoord2f[8];
249 float bloomtexcoord2f[8];
250 float offsettexcoord2f[8];
252 r_viewport_t viewport;
256 r_waterstate_t r_waterstate;
258 /// shadow volume bsp struct with automatically growing nodes buffer
261 rtexture_t *r_texture_blanknormalmap;
262 rtexture_t *r_texture_white;
263 rtexture_t *r_texture_grey128;
264 rtexture_t *r_texture_black;
265 rtexture_t *r_texture_notexture;
266 rtexture_t *r_texture_whitecube;
267 rtexture_t *r_texture_normalizationcube;
268 rtexture_t *r_texture_fogattenuation;
269 rtexture_t *r_texture_fogheighttexture;
270 rtexture_t *r_texture_gammaramps;
271 unsigned int r_texture_gammaramps_serial;
272 //rtexture_t *r_texture_fogintensity;
273 rtexture_t *r_texture_reflectcube;
275 // TODO: hash lookups?
276 typedef struct cubemapinfo_s
283 int r_texture_numcubemaps;
284 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
286 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
287 unsigned int r_numqueries;
288 unsigned int r_maxqueries;
290 typedef struct r_qwskincache_s
292 char name[MAX_QPATH];
293 skinframe_t *skinframe;
297 static r_qwskincache_t *r_qwskincache;
298 static int r_qwskincache_size;
300 /// vertex coordinates for a quad that covers the screen exactly
301 extern const float r_screenvertex3f[12];
302 extern const float r_d3dscreenvertex3f[12];
303 const float r_screenvertex3f[12] =
310 const float r_d3dscreenvertex3f[12] =
318 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
321 for (i = 0;i < verts;i++)
332 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
335 for (i = 0;i < verts;i++)
345 // FIXME: move this to client?
348 if (gamemode == GAME_NEHAHRA)
350 Cvar_Set("gl_fogenable", "0");
351 Cvar_Set("gl_fogdensity", "0.2");
352 Cvar_Set("gl_fogred", "0.3");
353 Cvar_Set("gl_foggreen", "0.3");
354 Cvar_Set("gl_fogblue", "0.3");
356 r_refdef.fog_density = 0;
357 r_refdef.fog_red = 0;
358 r_refdef.fog_green = 0;
359 r_refdef.fog_blue = 0;
360 r_refdef.fog_alpha = 1;
361 r_refdef.fog_start = 0;
362 r_refdef.fog_end = 16384;
363 r_refdef.fog_height = 1<<30;
364 r_refdef.fog_fadedepth = 128;
365 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
368 static void R_BuildBlankTextures(void)
370 unsigned char data[4];
371 data[2] = 128; // normal X
372 data[1] = 128; // normal Y
373 data[0] = 255; // normal Z
374 data[3] = 128; // height
375 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
380 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
385 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
390 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
393 static void R_BuildNoTexture(void)
396 unsigned char pix[16][16][4];
397 // this makes a light grey/dark grey checkerboard texture
398 for (y = 0;y < 16;y++)
400 for (x = 0;x < 16;x++)
402 if ((y < 8) ^ (x < 8))
418 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
421 static void R_BuildWhiteCube(void)
423 unsigned char data[6*1*1*4];
424 memset(data, 255, sizeof(data));
425 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
428 static void R_BuildNormalizationCube(void)
432 vec_t s, t, intensity;
435 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
436 for (side = 0;side < 6;side++)
438 for (y = 0;y < NORMSIZE;y++)
440 for (x = 0;x < NORMSIZE;x++)
442 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
443 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
478 intensity = 127.0f / sqrt(DotProduct(v, v));
479 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
480 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
481 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
482 data[((side*64+y)*64+x)*4+3] = 255;
486 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
490 static void R_BuildFogTexture(void)
494 unsigned char data1[FOGWIDTH][4];
495 //unsigned char data2[FOGWIDTH][4];
498 r_refdef.fogmasktable_start = r_refdef.fog_start;
499 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
500 r_refdef.fogmasktable_range = r_refdef.fogrange;
501 r_refdef.fogmasktable_density = r_refdef.fog_density;
503 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
504 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
506 d = (x * r - r_refdef.fogmasktable_start);
507 if(developer_extra.integer)
508 Con_DPrintf("%f ", d);
510 if (r_fog_exp2.integer)
511 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
513 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
514 if(developer_extra.integer)
515 Con_DPrintf(" : %f ", alpha);
516 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
517 if(developer_extra.integer)
518 Con_DPrintf(" = %f\n", alpha);
519 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
522 for (x = 0;x < FOGWIDTH;x++)
524 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
529 //data2[x][0] = 255 - b;
530 //data2[x][1] = 255 - b;
531 //data2[x][2] = 255 - b;
534 if (r_texture_fogattenuation)
536 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
537 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
541 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
542 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
546 static void R_BuildFogHeightTexture(void)
548 unsigned char *inpixels;
556 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
557 if (r_refdef.fogheighttexturename[0])
558 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
561 r_refdef.fog_height_tablesize = 0;
562 if (r_texture_fogheighttexture)
563 R_FreeTexture(r_texture_fogheighttexture);
564 r_texture_fogheighttexture = NULL;
565 if (r_refdef.fog_height_table2d)
566 Mem_Free(r_refdef.fog_height_table2d);
567 r_refdef.fog_height_table2d = NULL;
568 if (r_refdef.fog_height_table1d)
569 Mem_Free(r_refdef.fog_height_table1d);
570 r_refdef.fog_height_table1d = NULL;
574 r_refdef.fog_height_tablesize = size;
575 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
576 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
577 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
579 // LordHavoc: now the magic - what is that table2d for? it is a cooked
580 // average fog color table accounting for every fog layer between a point
581 // and the camera. (Note: attenuation is handled separately!)
582 for (y = 0;y < size;y++)
584 for (x = 0;x < size;x++)
590 for (j = x;j <= y;j++)
592 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
598 for (j = x;j >= y;j--)
600 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
605 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
606 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
607 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
608 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
611 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
614 //=======================================================================================================================================================
616 static const char *builtinshaderstring =
617 #include "shader_glsl.h"
620 const char *builtinhlslshaderstring =
621 #include "shader_hlsl.h"
624 char *glslshaderstring = NULL;
625 char *hlslshaderstring = NULL;
627 //=======================================================================================================================================================
629 typedef struct shaderpermutationinfo_s
634 shaderpermutationinfo_t;
636 typedef struct shadermodeinfo_s
638 const char *vertexfilename;
639 const char *geometryfilename;
640 const char *fragmentfilename;
646 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
647 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
649 {"#define USEDIFFUSE\n", " diffuse"},
650 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
651 {"#define USEVIEWTINT\n", " viewtint"},
652 {"#define USECOLORMAPPING\n", " colormapping"},
653 {"#define USESATURATION\n", " saturation"},
654 {"#define USEFOGINSIDE\n", " foginside"},
655 {"#define USEFOGOUTSIDE\n", " fogoutside"},
656 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
657 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
658 {"#define USEGAMMARAMPS\n", " gammaramps"},
659 {"#define USECUBEFILTER\n", " cubefilter"},
660 {"#define USEGLOW\n", " glow"},
661 {"#define USEBLOOM\n", " bloom"},
662 {"#define USESPECULAR\n", " specular"},
663 {"#define USEPOSTPROCESSING\n", " postprocessing"},
664 {"#define USEREFLECTION\n", " reflection"},
665 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
666 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
667 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
668 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
669 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
670 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
671 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
672 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
673 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
674 {"#define USEALPHAKILL\n", " alphakill"},
675 {"#define USEREFLECTCUBE\n", " reflectcube"},
676 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
677 {"#define USEBOUNCEGRID\n", " bouncegrid"},
678 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
681 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
682 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
684 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
685 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
686 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
687 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
688 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
689 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
690 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
691 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
692 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
693 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
694 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
695 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
696 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
697 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
698 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
699 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
702 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
704 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
705 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
706 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
707 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
708 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
709 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
710 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
711 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
712 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
713 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
714 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
715 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
716 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
717 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
718 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
719 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
722 struct r_glsl_permutation_s;
723 typedef struct r_glsl_permutation_s
726 struct r_glsl_permutation_s *hashnext;
728 unsigned int permutation;
730 /// indicates if we have tried compiling this permutation already
732 /// 0 if compilation failed
734 // texture units assigned to each detected uniform
735 int tex_Texture_First;
736 int tex_Texture_Second;
737 int tex_Texture_GammaRamps;
738 int tex_Texture_Normal;
739 int tex_Texture_Color;
740 int tex_Texture_Gloss;
741 int tex_Texture_Glow;
742 int tex_Texture_SecondaryNormal;
743 int tex_Texture_SecondaryColor;
744 int tex_Texture_SecondaryGloss;
745 int tex_Texture_SecondaryGlow;
746 int tex_Texture_Pants;
747 int tex_Texture_Shirt;
748 int tex_Texture_FogHeightTexture;
749 int tex_Texture_FogMask;
750 int tex_Texture_Lightmap;
751 int tex_Texture_Deluxemap;
752 int tex_Texture_Attenuation;
753 int tex_Texture_Cube;
754 int tex_Texture_Refraction;
755 int tex_Texture_Reflection;
756 int tex_Texture_ShadowMap2D;
757 int tex_Texture_CubeProjection;
758 int tex_Texture_ScreenDepth;
759 int tex_Texture_ScreenNormalMap;
760 int tex_Texture_ScreenDiffuse;
761 int tex_Texture_ScreenSpecular;
762 int tex_Texture_ReflectMask;
763 int tex_Texture_ReflectCube;
764 int tex_Texture_BounceGrid;
765 /// locations of detected uniforms in program object, or -1 if not found
766 int loc_Texture_First;
767 int loc_Texture_Second;
768 int loc_Texture_GammaRamps;
769 int loc_Texture_Normal;
770 int loc_Texture_Color;
771 int loc_Texture_Gloss;
772 int loc_Texture_Glow;
773 int loc_Texture_SecondaryNormal;
774 int loc_Texture_SecondaryColor;
775 int loc_Texture_SecondaryGloss;
776 int loc_Texture_SecondaryGlow;
777 int loc_Texture_Pants;
778 int loc_Texture_Shirt;
779 int loc_Texture_FogHeightTexture;
780 int loc_Texture_FogMask;
781 int loc_Texture_Lightmap;
782 int loc_Texture_Deluxemap;
783 int loc_Texture_Attenuation;
784 int loc_Texture_Cube;
785 int loc_Texture_Refraction;
786 int loc_Texture_Reflection;
787 int loc_Texture_ShadowMap2D;
788 int loc_Texture_CubeProjection;
789 int loc_Texture_ScreenDepth;
790 int loc_Texture_ScreenNormalMap;
791 int loc_Texture_ScreenDiffuse;
792 int loc_Texture_ScreenSpecular;
793 int loc_Texture_ReflectMask;
794 int loc_Texture_ReflectCube;
795 int loc_Texture_BounceGrid;
797 int loc_BloomBlur_Parameters;
799 int loc_Color_Ambient;
800 int loc_Color_Diffuse;
801 int loc_Color_Specular;
805 int loc_DeferredColor_Ambient;
806 int loc_DeferredColor_Diffuse;
807 int loc_DeferredColor_Specular;
808 int loc_DeferredMod_Diffuse;
809 int loc_DeferredMod_Specular;
810 int loc_DistortScaleRefractReflect;
813 int loc_FogHeightFade;
815 int loc_FogPlaneViewDist;
816 int loc_FogRangeRecip;
819 int loc_LightPosition;
820 int loc_OffsetMapping_ScaleSteps;
822 int loc_ReflectColor;
823 int loc_ReflectFactor;
824 int loc_ReflectOffset;
825 int loc_RefractColor;
827 int loc_ScreenCenterRefractReflect;
828 int loc_ScreenScaleRefractReflect;
829 int loc_ScreenToDepth;
830 int loc_ShadowMap_Parameters;
831 int loc_ShadowMap_TextureScale;
832 int loc_SpecularPower;
837 int loc_ViewTintColor;
839 int loc_ModelToLight;
841 int loc_BackgroundTexMatrix;
842 int loc_ModelViewProjectionMatrix;
843 int loc_ModelViewMatrix;
844 int loc_PixelToScreenTexCoord;
845 int loc_ModelToReflectCube;
846 int loc_ShadowMapMatrix;
847 int loc_BloomColorSubtract;
848 int loc_NormalmapScrollBlend;
849 int loc_BounceGridMatrix;
850 int loc_BounceGridIntensity;
852 r_glsl_permutation_t;
854 #define SHADERPERMUTATION_HASHSIZE 256
857 // non-degradable "lightweight" shader parameters to keep the permutations simpler
858 // these can NOT degrade! only use for simple stuff
861 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
862 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
863 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
864 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
865 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
866 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
867 SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
869 #define SHADERSTATICPARMS_COUNT 7
871 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
872 static int shaderstaticparms_count = 0;
874 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
875 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
876 qboolean R_CompileShader_CheckStaticParms(void)
878 static int r_compileshader_staticparms_save[1];
879 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
880 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
883 if (r_glsl_saturation_redcompensate.integer)
884 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
885 if (r_glsl_vertextextureblend_usebothalphas.integer)
886 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
887 if (r_shadow_glossexact.integer)
888 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
889 if (r_glsl_postprocess.integer)
891 if (r_glsl_postprocess_uservec1_enable.integer)
892 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
893 if (r_glsl_postprocess_uservec2_enable.integer)
894 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
895 if (r_glsl_postprocess_uservec3_enable.integer)
896 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
897 if (r_glsl_postprocess_uservec4_enable.integer)
898 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
900 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
903 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
904 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
905 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
907 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
908 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
910 shaderstaticparms_count = 0;
913 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
914 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
915 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
916 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
917 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
918 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
919 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
922 /// information about each possible shader permutation
923 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
924 /// currently selected permutation
925 r_glsl_permutation_t *r_glsl_permutation;
926 /// storage for permutations linked in the hash table
927 memexpandablearray_t r_glsl_permutationarray;
929 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
931 //unsigned int hashdepth = 0;
932 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
933 r_glsl_permutation_t *p;
934 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
936 if (p->mode == mode && p->permutation == permutation)
938 //if (hashdepth > 10)
939 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
944 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
946 p->permutation = permutation;
947 p->hashnext = r_glsl_permutationhash[mode][hashindex];
948 r_glsl_permutationhash[mode][hashindex] = p;
949 //if (hashdepth > 10)
950 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
954 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
957 if (!filename || !filename[0])
959 if (!strcmp(filename, "glsl/default.glsl"))
961 if (!glslshaderstring)
963 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
964 if (glslshaderstring)
965 Con_DPrintf("Loading shaders from file %s...\n", filename);
967 glslshaderstring = (char *)builtinshaderstring;
969 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
970 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
973 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
976 if (printfromdisknotice)
977 Con_DPrintf("from disk %s... ", filename);
983 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
987 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
988 char *vertexstring, *geometrystring, *fragmentstring;
989 char permutationname[256];
990 int vertstrings_count = 0;
991 int geomstrings_count = 0;
992 int fragstrings_count = 0;
993 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
994 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
995 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1002 permutationname[0] = 0;
1003 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1004 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1005 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1007 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1009 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1010 if(vid.support.gl20shaders130)
1012 vertstrings_list[vertstrings_count++] = "#version 130\n";
1013 geomstrings_list[geomstrings_count++] = "#version 130\n";
1014 fragstrings_list[fragstrings_count++] = "#version 130\n";
1015 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1016 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1017 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1020 // the first pretext is which type of shader to compile as
1021 // (later these will all be bound together as a program object)
1022 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1023 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1024 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1026 // the second pretext is the mode (for example a light source)
1027 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1028 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1029 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1030 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1032 // now add all the permutation pretexts
1033 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1035 if (permutation & (1<<i))
1037 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1038 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1039 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1040 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1044 // keep line numbers correct
1045 vertstrings_list[vertstrings_count++] = "\n";
1046 geomstrings_list[geomstrings_count++] = "\n";
1047 fragstrings_list[fragstrings_count++] = "\n";
1052 R_CompileShader_AddStaticParms(mode, permutation);
1053 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1054 vertstrings_count += shaderstaticparms_count;
1055 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1056 geomstrings_count += shaderstaticparms_count;
1057 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1058 fragstrings_count += shaderstaticparms_count;
1060 // now append the shader text itself
1061 vertstrings_list[vertstrings_count++] = vertexstring;
1062 geomstrings_list[geomstrings_count++] = geometrystring;
1063 fragstrings_list[fragstrings_count++] = fragmentstring;
1065 // if any sources were NULL, clear the respective list
1067 vertstrings_count = 0;
1068 if (!geometrystring)
1069 geomstrings_count = 0;
1070 if (!fragmentstring)
1071 fragstrings_count = 0;
1073 // compile the shader program
1074 if (vertstrings_count + geomstrings_count + fragstrings_count)
1075 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1079 qglUseProgram(p->program);CHECKGLERROR
1080 // look up all the uniform variable names we care about, so we don't
1081 // have to look them up every time we set them
1083 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1084 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1085 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1086 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1087 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1088 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1089 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1090 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1091 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1092 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1093 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1094 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1095 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1096 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1097 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1098 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1099 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1100 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1101 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1102 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1103 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1104 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1105 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1106 p->loc_Texture_ScreenDepth = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1107 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1108 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1109 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1110 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1111 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1112 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1113 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1114 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1115 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1116 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1117 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1118 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1119 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1120 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1121 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1122 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1123 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1124 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1125 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1126 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1127 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1128 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1129 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1130 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1131 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1132 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1133 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1134 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1135 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1136 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1137 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1138 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1139 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1140 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1141 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1142 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1143 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1144 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1145 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1146 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1147 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1148 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1149 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1150 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1151 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1152 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1153 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1154 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1155 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1156 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1157 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1158 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1159 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1160 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1161 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1162 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1163 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1164 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1165 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1166 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1167 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1168 // initialize the samplers to refer to the texture units we use
1169 p->tex_Texture_First = -1;
1170 p->tex_Texture_Second = -1;
1171 p->tex_Texture_GammaRamps = -1;
1172 p->tex_Texture_Normal = -1;
1173 p->tex_Texture_Color = -1;
1174 p->tex_Texture_Gloss = -1;
1175 p->tex_Texture_Glow = -1;
1176 p->tex_Texture_SecondaryNormal = -1;
1177 p->tex_Texture_SecondaryColor = -1;
1178 p->tex_Texture_SecondaryGloss = -1;
1179 p->tex_Texture_SecondaryGlow = -1;
1180 p->tex_Texture_Pants = -1;
1181 p->tex_Texture_Shirt = -1;
1182 p->tex_Texture_FogHeightTexture = -1;
1183 p->tex_Texture_FogMask = -1;
1184 p->tex_Texture_Lightmap = -1;
1185 p->tex_Texture_Deluxemap = -1;
1186 p->tex_Texture_Attenuation = -1;
1187 p->tex_Texture_Cube = -1;
1188 p->tex_Texture_Refraction = -1;
1189 p->tex_Texture_Reflection = -1;
1190 p->tex_Texture_ShadowMap2D = -1;
1191 p->tex_Texture_CubeProjection = -1;
1192 p->tex_Texture_ScreenDepth = -1;
1193 p->tex_Texture_ScreenNormalMap = -1;
1194 p->tex_Texture_ScreenDiffuse = -1;
1195 p->tex_Texture_ScreenSpecular = -1;
1196 p->tex_Texture_ReflectMask = -1;
1197 p->tex_Texture_ReflectCube = -1;
1198 p->tex_Texture_BounceGrid = -1;
1200 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1201 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1202 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1203 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1204 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1205 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1206 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1207 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1208 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1209 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1210 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1211 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1212 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1213 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1214 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1215 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1216 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1217 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1218 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1219 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1220 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1221 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1222 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1223 if (p->loc_Texture_ScreenDepth >= 0) {p->tex_Texture_ScreenDepth = sampler;qglUniform1i(p->loc_Texture_ScreenDepth , sampler);sampler++;}
1224 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1225 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1226 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1227 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1228 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1229 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1231 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1234 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1238 Mem_Free(vertexstring);
1240 Mem_Free(geometrystring);
1242 Mem_Free(fragmentstring);
1245 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1247 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1248 if (r_glsl_permutation != perm)
1250 r_glsl_permutation = perm;
1251 if (!r_glsl_permutation->program)
1253 if (!r_glsl_permutation->compiled)
1254 R_GLSL_CompilePermutation(perm, mode, permutation);
1255 if (!r_glsl_permutation->program)
1257 // remove features until we find a valid permutation
1259 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1261 // reduce i more quickly whenever it would not remove any bits
1262 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1263 if (!(permutation & j))
1266 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1267 if (!r_glsl_permutation->compiled)
1268 R_GLSL_CompilePermutation(perm, mode, permutation);
1269 if (r_glsl_permutation->program)
1272 if (i >= SHADERPERMUTATION_COUNT)
1274 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1275 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1276 qglUseProgram(0);CHECKGLERROR
1277 return; // no bit left to clear, entire mode is broken
1282 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1284 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1285 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1286 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1293 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1294 extern D3DCAPS9 vid_d3d9caps;
1297 struct r_hlsl_permutation_s;
1298 typedef struct r_hlsl_permutation_s
1300 /// hash lookup data
1301 struct r_hlsl_permutation_s *hashnext;
1303 unsigned int permutation;
1305 /// indicates if we have tried compiling this permutation already
1307 /// NULL if compilation failed
1308 IDirect3DVertexShader9 *vertexshader;
1309 IDirect3DPixelShader9 *pixelshader;
1311 r_hlsl_permutation_t;
1313 typedef enum D3DVSREGISTER_e
1315 D3DVSREGISTER_TexMatrix = 0, // float4x4
1316 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1317 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1318 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1319 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1320 D3DVSREGISTER_ModelToLight = 20, // float4x4
1321 D3DVSREGISTER_EyePosition = 24,
1322 D3DVSREGISTER_FogPlane = 25,
1323 D3DVSREGISTER_LightDir = 26,
1324 D3DVSREGISTER_LightPosition = 27,
1328 typedef enum D3DPSREGISTER_e
1330 D3DPSREGISTER_Alpha = 0,
1331 D3DPSREGISTER_BloomBlur_Parameters = 1,
1332 D3DPSREGISTER_ClientTime = 2,
1333 D3DPSREGISTER_Color_Ambient = 3,
1334 D3DPSREGISTER_Color_Diffuse = 4,
1335 D3DPSREGISTER_Color_Specular = 5,
1336 D3DPSREGISTER_Color_Glow = 6,
1337 D3DPSREGISTER_Color_Pants = 7,
1338 D3DPSREGISTER_Color_Shirt = 8,
1339 D3DPSREGISTER_DeferredColor_Ambient = 9,
1340 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1341 D3DPSREGISTER_DeferredColor_Specular = 11,
1342 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1343 D3DPSREGISTER_DeferredMod_Specular = 13,
1344 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1345 D3DPSREGISTER_EyePosition = 15, // unused
1346 D3DPSREGISTER_FogColor = 16,
1347 D3DPSREGISTER_FogHeightFade = 17,
1348 D3DPSREGISTER_FogPlane = 18,
1349 D3DPSREGISTER_FogPlaneViewDist = 19,
1350 D3DPSREGISTER_FogRangeRecip = 20,
1351 D3DPSREGISTER_LightColor = 21,
1352 D3DPSREGISTER_LightDir = 22, // unused
1353 D3DPSREGISTER_LightPosition = 23,
1354 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1355 D3DPSREGISTER_PixelSize = 25,
1356 D3DPSREGISTER_ReflectColor = 26,
1357 D3DPSREGISTER_ReflectFactor = 27,
1358 D3DPSREGISTER_ReflectOffset = 28,
1359 D3DPSREGISTER_RefractColor = 29,
1360 D3DPSREGISTER_Saturation = 30,
1361 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1362 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1363 D3DPSREGISTER_ScreenToDepth = 33,
1364 D3DPSREGISTER_ShadowMap_Parameters = 34,
1365 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1366 D3DPSREGISTER_SpecularPower = 36,
1367 D3DPSREGISTER_UserVec1 = 37,
1368 D3DPSREGISTER_UserVec2 = 38,
1369 D3DPSREGISTER_UserVec3 = 39,
1370 D3DPSREGISTER_UserVec4 = 40,
1371 D3DPSREGISTER_ViewTintColor = 41,
1372 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1373 D3DPSREGISTER_BloomColorSubtract = 43,
1374 D3DPSREGISTER_ViewToLight = 44, // float4x4
1375 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1376 D3DPSREGISTER_NormalmapScrollBlend = 52,
1381 /// information about each possible shader permutation
1382 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1383 /// currently selected permutation
1384 r_hlsl_permutation_t *r_hlsl_permutation;
1385 /// storage for permutations linked in the hash table
1386 memexpandablearray_t r_hlsl_permutationarray;
1388 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1390 //unsigned int hashdepth = 0;
1391 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1392 r_hlsl_permutation_t *p;
1393 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1395 if (p->mode == mode && p->permutation == permutation)
1397 //if (hashdepth > 10)
1398 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1403 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1405 p->permutation = permutation;
1406 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1407 r_hlsl_permutationhash[mode][hashindex] = p;
1408 //if (hashdepth > 10)
1409 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1413 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1416 if (!filename || !filename[0])
1418 if (!strcmp(filename, "hlsl/default.hlsl"))
1420 if (!hlslshaderstring)
1422 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1423 if (hlslshaderstring)
1424 Con_DPrintf("Loading shaders from file %s...\n", filename);
1426 hlslshaderstring = (char *)builtinhlslshaderstring;
1428 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1429 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1430 return shaderstring;
1432 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1435 if (printfromdisknotice)
1436 Con_DPrintf("from disk %s... ", filename);
1437 return shaderstring;
1439 return shaderstring;
1443 //#include <d3dx9shader.h>
1444 //#include <d3dx9mesh.h>
1446 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1448 DWORD *vsbin = NULL;
1449 DWORD *psbin = NULL;
1450 fs_offset_t vsbinsize;
1451 fs_offset_t psbinsize;
1452 // IDirect3DVertexShader9 *vs = NULL;
1453 // IDirect3DPixelShader9 *ps = NULL;
1454 ID3DXBuffer *vslog = NULL;
1455 ID3DXBuffer *vsbuffer = NULL;
1456 ID3DXConstantTable *vsconstanttable = NULL;
1457 ID3DXBuffer *pslog = NULL;
1458 ID3DXBuffer *psbuffer = NULL;
1459 ID3DXConstantTable *psconstanttable = NULL;
1462 char temp[MAX_INPUTLINE];
1463 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1464 qboolean debugshader = gl_paranoid.integer != 0;
1465 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1466 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1469 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1470 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1472 if ((!vsbin && vertstring) || (!psbin && fragstring))
1474 const char* dllnames_d3dx9 [] =
1498 dllhandle_t d3dx9_dll = NULL;
1499 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1500 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1501 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1502 dllfunction_t d3dx9_dllfuncs[] =
1504 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1505 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1506 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1509 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1511 DWORD shaderflags = 0;
1513 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1514 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1515 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1516 if (vertstring && vertstring[0])
1520 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1521 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1522 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1523 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1526 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1529 vsbinsize = vsbuffer->GetBufferSize();
1530 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1531 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1532 vsbuffer->Release();
1536 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1537 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1541 if (fragstring && fragstring[0])
1545 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1546 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1547 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1548 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1551 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1554 psbinsize = psbuffer->GetBufferSize();
1555 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1556 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1557 psbuffer->Release();
1561 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1562 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1566 Sys_UnloadLibrary(&d3dx9_dll);
1569 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1573 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1574 if (FAILED(vsresult))
1575 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1576 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1577 if (FAILED(psresult))
1578 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1580 // free the shader data
1581 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1582 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1585 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1588 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1589 int vertstring_length = 0;
1590 int geomstring_length = 0;
1591 int fragstring_length = 0;
1593 char *vertexstring, *geometrystring, *fragmentstring;
1594 char *vertstring, *geomstring, *fragstring;
1595 char permutationname[256];
1596 char cachename[256];
1597 int vertstrings_count = 0;
1598 int geomstrings_count = 0;
1599 int fragstrings_count = 0;
1600 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1601 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1602 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1607 p->vertexshader = NULL;
1608 p->pixelshader = NULL;
1610 permutationname[0] = 0;
1612 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
1613 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1614 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1616 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1617 strlcat(cachename, "hlsl/", sizeof(cachename));
1619 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1620 vertstrings_count = 0;
1621 geomstrings_count = 0;
1622 fragstrings_count = 0;
1623 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1624 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1625 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1627 // the first pretext is which type of shader to compile as
1628 // (later these will all be bound together as a program object)
1629 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1630 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1631 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1633 // the second pretext is the mode (for example a light source)
1634 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1635 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1636 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1637 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1638 strlcat(cachename, modeinfo->name, sizeof(cachename));
1640 // now add all the permutation pretexts
1641 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1643 if (permutation & (1<<i))
1645 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1646 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1647 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1648 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1649 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1653 // keep line numbers correct
1654 vertstrings_list[vertstrings_count++] = "\n";
1655 geomstrings_list[geomstrings_count++] = "\n";
1656 fragstrings_list[fragstrings_count++] = "\n";
1661 R_CompileShader_AddStaticParms(mode, permutation);
1662 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1663 vertstrings_count += shaderstaticparms_count;
1664 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1665 geomstrings_count += shaderstaticparms_count;
1666 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1667 fragstrings_count += shaderstaticparms_count;
1669 // replace spaces in the cachename with _ characters
1670 for (i = 0;cachename[i];i++)
1671 if (cachename[i] == ' ')
1674 // now append the shader text itself
1675 vertstrings_list[vertstrings_count++] = vertexstring;
1676 geomstrings_list[geomstrings_count++] = geometrystring;
1677 fragstrings_list[fragstrings_count++] = fragmentstring;
1679 // if any sources were NULL, clear the respective list
1681 vertstrings_count = 0;
1682 if (!geometrystring)
1683 geomstrings_count = 0;
1684 if (!fragmentstring)
1685 fragstrings_count = 0;
1687 vertstring_length = 0;
1688 for (i = 0;i < vertstrings_count;i++)
1689 vertstring_length += strlen(vertstrings_list[i]);
1690 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1691 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1692 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1694 geomstring_length = 0;
1695 for (i = 0;i < geomstrings_count;i++)
1696 geomstring_length += strlen(geomstrings_list[i]);
1697 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1698 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1699 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1701 fragstring_length = 0;
1702 for (i = 0;i < fragstrings_count;i++)
1703 fragstring_length += strlen(fragstrings_list[i]);
1704 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1705 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1706 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1708 // try to load the cached shader, or generate one
1709 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1711 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1712 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1714 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1718 Mem_Free(vertstring);
1720 Mem_Free(geomstring);
1722 Mem_Free(fragstring);
1724 Mem_Free(vertexstring);
1726 Mem_Free(geometrystring);
1728 Mem_Free(fragmentstring);
1731 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1732 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1733 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);}
1734 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);}
1735 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);}
1736 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);}
1738 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1739 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1740 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);}
1741 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);}
1742 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);}
1743 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);}
1745 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1747 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1748 if (r_hlsl_permutation != perm)
1750 r_hlsl_permutation = perm;
1751 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1753 if (!r_hlsl_permutation->compiled)
1754 R_HLSL_CompilePermutation(perm, mode, permutation);
1755 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1757 // remove features until we find a valid permutation
1759 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1761 // reduce i more quickly whenever it would not remove any bits
1762 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1763 if (!(permutation & j))
1766 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1767 if (!r_hlsl_permutation->compiled)
1768 R_HLSL_CompilePermutation(perm, mode, permutation);
1769 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1772 if (i >= SHADERPERMUTATION_COUNT)
1774 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1775 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1776 return; // no bit left to clear, entire mode is broken
1780 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1781 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1783 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1784 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1785 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1789 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1791 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1792 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1793 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1794 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1797 void R_GLSL_Restart_f(void)
1799 unsigned int i, limit;
1800 if (glslshaderstring && glslshaderstring != builtinshaderstring)
1801 Mem_Free(glslshaderstring);
1802 glslshaderstring = NULL;
1803 if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1804 Mem_Free(hlslshaderstring);
1805 hlslshaderstring = NULL;
1806 switch(vid.renderpath)
1808 case RENDERPATH_D3D9:
1811 r_hlsl_permutation_t *p;
1812 r_hlsl_permutation = NULL;
1813 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1814 for (i = 0;i < limit;i++)
1816 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1818 if (p->vertexshader)
1819 IDirect3DVertexShader9_Release(p->vertexshader);
1821 IDirect3DPixelShader9_Release(p->pixelshader);
1822 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1825 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1829 case RENDERPATH_D3D10:
1830 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1832 case RENDERPATH_D3D11:
1833 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1835 case RENDERPATH_GL20:
1836 case RENDERPATH_GLES2:
1838 r_glsl_permutation_t *p;
1839 r_glsl_permutation = NULL;
1840 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1841 for (i = 0;i < limit;i++)
1843 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1845 GL_Backend_FreeProgram(p->program);
1846 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1849 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1852 case RENDERPATH_GL13:
1853 case RENDERPATH_GL11:
1855 case RENDERPATH_SOFT:
1860 void R_GLSL_DumpShader_f(void)
1865 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1868 FS_Print(file, "/* The engine may define the following macros:\n");
1869 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1870 for (i = 0;i < SHADERMODE_COUNT;i++)
1871 FS_Print(file, glslshadermodeinfo[i].pretext);
1872 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1873 FS_Print(file, shaderpermutationinfo[i].pretext);
1874 FS_Print(file, "*/\n");
1875 FS_Print(file, builtinshaderstring);
1877 Con_Printf("glsl/default.glsl written\n");
1880 Con_Printf("failed to write to glsl/default.glsl\n");
1882 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1885 FS_Print(file, "/* The engine may define the following macros:\n");
1886 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1887 for (i = 0;i < SHADERMODE_COUNT;i++)
1888 FS_Print(file, hlslshadermodeinfo[i].pretext);
1889 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1890 FS_Print(file, shaderpermutationinfo[i].pretext);
1891 FS_Print(file, "*/\n");
1892 FS_Print(file, builtinhlslshaderstring);
1894 Con_Printf("hlsl/default.hlsl written\n");
1897 Con_Printf("failed to write to hlsl/default.hlsl\n");
1900 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1903 texturemode = GL_MODULATE;
1904 switch (vid.renderpath)
1906 case RENDERPATH_D3D9:
1908 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))));
1909 R_Mesh_TexBind(GL20TU_FIRST , first );
1910 R_Mesh_TexBind(GL20TU_SECOND, second);
1913 case RENDERPATH_D3D10:
1914 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1916 case RENDERPATH_D3D11:
1917 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1919 case RENDERPATH_GL20:
1920 case RENDERPATH_GLES2:
1921 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))));
1922 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1923 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1925 case RENDERPATH_GL13:
1926 R_Mesh_TexBind(0, first );
1927 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1928 R_Mesh_TexBind(1, second);
1930 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1932 case RENDERPATH_GL11:
1933 R_Mesh_TexBind(0, first );
1935 case RENDERPATH_SOFT:
1936 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))));
1937 R_Mesh_TexBind(GL20TU_FIRST , first );
1938 R_Mesh_TexBind(GL20TU_SECOND, second);
1943 void R_SetupShader_DepthOrShadow(void)
1945 switch (vid.renderpath)
1947 case RENDERPATH_D3D9:
1949 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1952 case RENDERPATH_D3D10:
1953 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1955 case RENDERPATH_D3D11:
1956 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1958 case RENDERPATH_GL20:
1959 case RENDERPATH_GLES2:
1960 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1962 case RENDERPATH_GL13:
1963 R_Mesh_TexBind(0, 0);
1964 R_Mesh_TexBind(1, 0);
1966 case RENDERPATH_GL11:
1967 R_Mesh_TexBind(0, 0);
1969 case RENDERPATH_SOFT:
1970 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1975 void R_SetupShader_ShowDepth(void)
1977 switch (vid.renderpath)
1979 case RENDERPATH_D3D9:
1981 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1984 case RENDERPATH_D3D10:
1985 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1987 case RENDERPATH_D3D11:
1988 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1990 case RENDERPATH_GL20:
1991 case RENDERPATH_GLES2:
1992 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1994 case RENDERPATH_GL13:
1996 case RENDERPATH_GL11:
1998 case RENDERPATH_SOFT:
1999 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
2004 extern qboolean r_shadow_usingdeferredprepass;
2005 extern cvar_t r_shadow_deferred_8bitrange;
2006 extern rtexture_t *r_shadow_attenuationgradienttexture;
2007 extern rtexture_t *r_shadow_attenuation2dtexture;
2008 extern rtexture_t *r_shadow_attenuation3dtexture;
2009 extern qboolean r_shadow_usingshadowmap2d;
2010 extern qboolean r_shadow_usingshadowmaportho;
2011 extern float r_shadow_shadowmap_texturescale[2];
2012 extern float r_shadow_shadowmap_parameters[4];
2013 extern qboolean r_shadow_shadowmapvsdct;
2014 extern qboolean r_shadow_shadowmapsampler;
2015 extern int r_shadow_shadowmappcf;
2016 extern rtexture_t *r_shadow_shadowmap2dtexture;
2017 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2018 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2019 extern matrix4x4_t r_shadow_shadowmapmatrix;
2020 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2021 extern int r_shadow_prepass_width;
2022 extern int r_shadow_prepass_height;
2023 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2024 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2025 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2026 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2027 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2029 #define BLENDFUNC_ALLOWS_COLORMOD 1
2030 #define BLENDFUNC_ALLOWS_FOG 2
2031 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2032 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2033 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2034 static int R_BlendFuncFlags(int src, int dst)
2038 // a blendfunc allows colormod if:
2039 // a) it can never keep the destination pixel invariant, or
2040 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2041 // this is to prevent unintended side effects from colormod
2043 // a blendfunc allows fog if:
2044 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2045 // this is to prevent unintended side effects from fog
2047 // these checks are the output of fogeval.pl
2049 r |= BLENDFUNC_ALLOWS_COLORMOD;
2050 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2051 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2052 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2053 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2054 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2055 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2056 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2057 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2058 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2059 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2060 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2061 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2062 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2063 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2064 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2065 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2066 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2067 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2068 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2069 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2070 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2075 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)
2077 // select a permutation of the lighting shader appropriate to this
2078 // combination of texture, entity, light source, and fogging, only use the
2079 // minimum features necessary to avoid wasting rendering time in the
2080 // fragment shader on features that are not being used
2081 unsigned int permutation = 0;
2082 unsigned int mode = 0;
2084 static float dummy_colormod[3] = {1, 1, 1};
2085 float *colormod = rsurface.colormod;
2087 matrix4x4_t tempmatrix;
2088 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2089 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2090 permutation |= SHADERPERMUTATION_ALPHAKILL;
2091 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2092 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2093 if (rsurfacepass == RSURFPASS_BACKGROUND)
2095 // distorted background
2096 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2098 mode = SHADERMODE_WATER;
2099 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2101 // this is the right thing to do for wateralpha
2102 GL_BlendFunc(GL_ONE, GL_ZERO);
2103 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2107 // this is the right thing to do for entity alpha
2108 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2109 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2112 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2114 mode = SHADERMODE_REFRACTION;
2115 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2116 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2120 mode = SHADERMODE_GENERIC;
2121 permutation |= SHADERPERMUTATION_DIFFUSE;
2122 GL_BlendFunc(GL_ONE, GL_ZERO);
2123 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2126 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2128 if (r_glsl_offsetmapping.integer)
2130 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2131 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2132 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2133 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2134 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2136 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2137 if (r_glsl_offsetmapping_reliefmapping.integer)
2138 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2141 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2142 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2143 // normalmap (deferred prepass), may use alpha test on diffuse
2144 mode = SHADERMODE_DEFERREDGEOMETRY;
2145 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2146 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2147 GL_BlendFunc(GL_ONE, GL_ZERO);
2148 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2150 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2152 if (r_glsl_offsetmapping.integer)
2154 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2155 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2156 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2157 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2158 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2160 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2161 if (r_glsl_offsetmapping_reliefmapping.integer)
2162 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2165 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2166 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2168 mode = SHADERMODE_LIGHTSOURCE;
2169 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2170 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2171 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2172 permutation |= SHADERPERMUTATION_CUBEFILTER;
2173 if (diffusescale > 0)
2174 permutation |= SHADERPERMUTATION_DIFFUSE;
2175 if (specularscale > 0)
2176 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2177 if (r_refdef.fogenabled)
2178 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2179 if (rsurface.texture->colormapping)
2180 permutation |= SHADERPERMUTATION_COLORMAPPING;
2181 if (r_shadow_usingshadowmap2d)
2183 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2184 if(r_shadow_shadowmapvsdct)
2185 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2187 if (r_shadow_shadowmapsampler)
2188 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2189 if (r_shadow_shadowmappcf > 1)
2190 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2191 else if (r_shadow_shadowmappcf)
2192 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2194 if (rsurface.texture->reflectmasktexture)
2195 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2196 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2197 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2199 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2201 if (r_glsl_offsetmapping.integer)
2203 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2204 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2205 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2206 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2207 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2209 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2210 if (r_glsl_offsetmapping_reliefmapping.integer)
2211 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2214 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2215 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2216 // unshaded geometry (fullbright or ambient model lighting)
2217 mode = SHADERMODE_FLATCOLOR;
2218 ambientscale = diffusescale = specularscale = 0;
2219 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2220 permutation |= SHADERPERMUTATION_GLOW;
2221 if (r_refdef.fogenabled)
2222 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2223 if (rsurface.texture->colormapping)
2224 permutation |= SHADERPERMUTATION_COLORMAPPING;
2225 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2227 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2228 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2230 if (r_shadow_shadowmapsampler)
2231 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2232 if (r_shadow_shadowmappcf > 1)
2233 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2234 else if (r_shadow_shadowmappcf)
2235 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2237 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2238 permutation |= SHADERPERMUTATION_REFLECTION;
2239 if (rsurface.texture->reflectmasktexture)
2240 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2241 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2242 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2244 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2246 if (r_glsl_offsetmapping.integer)
2248 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2249 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2250 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2251 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2252 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2254 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2255 if (r_glsl_offsetmapping_reliefmapping.integer)
2256 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2259 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2260 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2261 // directional model lighting
2262 mode = SHADERMODE_LIGHTDIRECTION;
2263 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2264 permutation |= SHADERPERMUTATION_GLOW;
2265 permutation |= SHADERPERMUTATION_DIFFUSE;
2266 if (specularscale > 0)
2267 permutation |= SHADERPERMUTATION_SPECULAR;
2268 if (r_refdef.fogenabled)
2269 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2270 if (rsurface.texture->colormapping)
2271 permutation |= SHADERPERMUTATION_COLORMAPPING;
2272 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2274 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2275 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2277 if (r_shadow_shadowmapsampler)
2278 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2279 if (r_shadow_shadowmappcf > 1)
2280 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2281 else if (r_shadow_shadowmappcf)
2282 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2284 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2285 permutation |= SHADERPERMUTATION_REFLECTION;
2286 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2287 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2288 if (rsurface.texture->reflectmasktexture)
2289 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2290 if (r_shadow_bouncegridtexture)
2292 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2293 if (r_shadow_bouncegriddirectional)
2294 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2296 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2297 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2299 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2301 if (r_glsl_offsetmapping.integer)
2303 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2304 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2305 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2306 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2307 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2309 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2310 if (r_glsl_offsetmapping_reliefmapping.integer)
2311 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2314 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2315 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2316 // ambient model lighting
2317 mode = SHADERMODE_LIGHTDIRECTION;
2318 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2319 permutation |= SHADERPERMUTATION_GLOW;
2320 if (r_refdef.fogenabled)
2321 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2322 if (rsurface.texture->colormapping)
2323 permutation |= SHADERPERMUTATION_COLORMAPPING;
2324 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2326 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2327 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2329 if (r_shadow_shadowmapsampler)
2330 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2331 if (r_shadow_shadowmappcf > 1)
2332 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2333 else if (r_shadow_shadowmappcf)
2334 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2336 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2337 permutation |= SHADERPERMUTATION_REFLECTION;
2338 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2339 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2340 if (rsurface.texture->reflectmasktexture)
2341 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2342 if (r_shadow_bouncegridtexture)
2344 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2345 if (r_shadow_bouncegriddirectional)
2346 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2348 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2349 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2353 if (r_glsl_offsetmapping.integer)
2355 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2356 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2357 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2358 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2359 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2361 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2362 if (r_glsl_offsetmapping_reliefmapping.integer)
2363 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2366 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2367 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2369 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2370 permutation |= SHADERPERMUTATION_GLOW;
2371 if (r_refdef.fogenabled)
2372 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2373 if (rsurface.texture->colormapping)
2374 permutation |= SHADERPERMUTATION_COLORMAPPING;
2375 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2377 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2378 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2380 if (r_shadow_shadowmapsampler)
2381 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2382 if (r_shadow_shadowmappcf > 1)
2383 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2384 else if (r_shadow_shadowmappcf)
2385 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2387 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2388 permutation |= SHADERPERMUTATION_REFLECTION;
2389 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2390 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2391 if (rsurface.texture->reflectmasktexture)
2392 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2393 if (FAKELIGHT_ENABLED)
2395 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2396 mode = SHADERMODE_FAKELIGHT;
2397 permutation |= SHADERPERMUTATION_DIFFUSE;
2398 if (specularscale > 0)
2399 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2401 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2403 // deluxemapping (light direction texture)
2404 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2405 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2407 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2408 permutation |= SHADERPERMUTATION_DIFFUSE;
2409 if (specularscale > 0)
2410 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2412 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2414 // fake deluxemapping (uniform light direction in tangentspace)
2415 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2416 permutation |= SHADERPERMUTATION_DIFFUSE;
2417 if (specularscale > 0)
2418 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2420 else if (rsurface.uselightmaptexture)
2422 // ordinary lightmapping (q1bsp, q3bsp)
2423 mode = SHADERMODE_LIGHTMAP;
2427 // ordinary vertex coloring (q3bsp)
2428 mode = SHADERMODE_VERTEXCOLOR;
2430 if (r_shadow_bouncegridtexture)
2432 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2433 if (r_shadow_bouncegriddirectional)
2434 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2436 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2437 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2439 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2440 colormod = dummy_colormod;
2441 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2442 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2443 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2444 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2445 switch(vid.renderpath)
2447 case RENDERPATH_D3D9:
2449 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);
2450 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2451 R_SetupShader_SetPermutationHLSL(mode, permutation);
2452 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2453 if (mode == SHADERMODE_LIGHTSOURCE)
2455 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2456 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2460 if (mode == SHADERMODE_LIGHTDIRECTION)
2462 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2465 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2466 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2467 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2468 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2469 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2471 if (mode == SHADERMODE_LIGHTSOURCE)
2473 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2474 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2475 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2476 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2477 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2479 // additive passes are only darkened by fog, not tinted
2480 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2481 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2485 if (mode == SHADERMODE_FLATCOLOR)
2487 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2489 else if (mode == SHADERMODE_LIGHTDIRECTION)
2491 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]);
2492 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2493 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);
2494 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);
2495 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2496 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2497 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2501 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2502 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2503 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);
2504 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);
2505 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2507 // additive passes are only darkened by fog, not tinted
2508 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2509 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2511 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2512 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);
2513 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2514 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2515 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2516 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2517 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2518 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2519 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2520 if (mode == SHADERMODE_WATER)
2521 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2523 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2524 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2525 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2526 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));
2527 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2528 if (rsurface.texture->pantstexture)
2529 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2531 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2532 if (rsurface.texture->shirttexture)
2533 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2535 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2536 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2537 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2538 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2539 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2540 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));
2541 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2542 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2544 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2545 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2546 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2547 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2548 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2549 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2550 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2551 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2552 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2553 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2554 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2555 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2556 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2557 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2558 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2559 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2560 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2561 if (rsurfacepass == RSURFPASS_BACKGROUND)
2563 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2564 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2565 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2569 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2571 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2572 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2573 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2574 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2575 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2577 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2578 if (rsurface.rtlight)
2580 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2581 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2586 case RENDERPATH_D3D10:
2587 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2589 case RENDERPATH_D3D11:
2590 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2592 case RENDERPATH_GL20:
2593 case RENDERPATH_GLES2:
2594 if (!vid.useinterleavedarrays)
2596 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);
2597 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2598 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2599 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2600 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2601 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2602 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2603 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2607 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);
2608 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2610 R_SetupShader_SetPermutationGLSL(mode, permutation);
2611 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2612 if (mode == SHADERMODE_LIGHTSOURCE)
2614 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2615 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2616 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2617 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2618 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2619 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);
2621 // additive passes are only darkened by fog, not tinted
2622 if (r_glsl_permutation->loc_FogColor >= 0)
2623 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2624 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2628 if (mode == SHADERMODE_FLATCOLOR)
2630 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2632 else if (mode == SHADERMODE_LIGHTDIRECTION)
2634 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]);
2635 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]);
2636 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);
2637 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);
2638 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);
2639 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]);
2640 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]);
2644 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]);
2645 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]);
2646 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);
2647 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);
2648 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);
2650 // additive passes are only darkened by fog, not tinted
2651 if (r_glsl_permutation->loc_FogColor >= 0)
2653 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2654 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2656 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2658 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);
2659 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]);
2660 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]);
2661 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]);
2662 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]);
2663 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2664 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2665 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2666 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]);
2668 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2669 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2670 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2671 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]);
2672 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]);
2674 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2675 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));
2676 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2677 if (r_glsl_permutation->loc_Color_Pants >= 0)
2679 if (rsurface.texture->pantstexture)
2680 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2682 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2684 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2686 if (rsurface.texture->shirttexture)
2687 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2689 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2691 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]);
2692 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2693 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2694 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2695 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));
2696 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]);
2697 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2698 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);}
2699 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2701 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2702 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2703 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2704 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2705 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2706 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2707 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2708 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2709 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2710 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2711 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2712 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2713 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2714 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2715 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);
2716 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2717 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2718 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2719 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2720 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2721 if (rsurfacepass == RSURFPASS_BACKGROUND)
2723 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);
2724 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);
2725 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);
2729 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);
2731 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2732 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2733 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2734 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2735 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2737 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
2738 if (rsurface.rtlight)
2740 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2741 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2744 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2747 case RENDERPATH_GL13:
2748 case RENDERPATH_GL11:
2750 case RENDERPATH_SOFT:
2751 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);
2752 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2753 R_SetupShader_SetPermutationSoft(mode, permutation);
2754 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2755 if (mode == SHADERMODE_LIGHTSOURCE)
2757 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2758 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2759 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2760 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2761 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2762 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2764 // additive passes are only darkened by fog, not tinted
2765 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2766 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2770 if (mode == SHADERMODE_FLATCOLOR)
2772 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2774 else if (mode == SHADERMODE_LIGHTDIRECTION)
2776 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]);
2777 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2778 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);
2779 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);
2780 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2781 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]);
2782 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2786 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2787 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2788 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);
2789 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);
2790 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2792 // additive passes are only darkened by fog, not tinted
2793 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2794 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2796 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2797 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);
2798 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2799 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2800 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]);
2801 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]);
2802 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2803 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2804 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2805 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2807 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2808 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2809 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2810 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2811 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]);
2813 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2814 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));
2815 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2816 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2818 if (rsurface.texture->pantstexture)
2819 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2821 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2823 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2825 if (rsurface.texture->shirttexture)
2826 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2828 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2830 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2831 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2832 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2833 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2834 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));
2835 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2836 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2838 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2839 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2840 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2841 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2842 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2843 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2844 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2845 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2846 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2847 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2848 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2849 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2850 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2851 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2852 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2853 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2854 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2855 if (rsurfacepass == RSURFPASS_BACKGROUND)
2857 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2858 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2859 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2863 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2865 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2866 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2867 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2868 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2869 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2871 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2872 if (rsurface.rtlight)
2874 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2875 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2882 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2884 // select a permutation of the lighting shader appropriate to this
2885 // combination of texture, entity, light source, and fogging, only use the
2886 // minimum features necessary to avoid wasting rendering time in the
2887 // fragment shader on features that are not being used
2888 unsigned int permutation = 0;
2889 unsigned int mode = 0;
2890 const float *lightcolorbase = rtlight->currentcolor;
2891 float ambientscale = rtlight->ambientscale;
2892 float diffusescale = rtlight->diffusescale;
2893 float specularscale = rtlight->specularscale;
2894 // this is the location of the light in view space
2895 vec3_t viewlightorigin;
2896 // this transforms from view space (camera) to light space (cubemap)
2897 matrix4x4_t viewtolight;
2898 matrix4x4_t lighttoview;
2899 float viewtolight16f[16];
2900 float range = 1.0f / r_shadow_deferred_8bitrange.value;
2902 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2903 if (rtlight->currentcubemap != r_texture_whitecube)
2904 permutation |= SHADERPERMUTATION_CUBEFILTER;
2905 if (diffusescale > 0)
2906 permutation |= SHADERPERMUTATION_DIFFUSE;
2907 if (specularscale > 0 && r_shadow_gloss.integer > 0)
2908 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2909 if (r_shadow_usingshadowmap2d)
2911 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2912 if (r_shadow_shadowmapvsdct)
2913 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2915 if (r_shadow_shadowmapsampler)
2916 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2917 if (r_shadow_shadowmappcf > 1)
2918 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2919 else if (r_shadow_shadowmappcf)
2920 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2922 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2923 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2924 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2925 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2926 switch(vid.renderpath)
2928 case RENDERPATH_D3D9:
2930 R_SetupShader_SetPermutationHLSL(mode, permutation);
2931 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2932 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2933 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2934 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2935 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2936 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2937 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2938 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2939 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2940 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2942 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2943 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
2944 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2945 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2946 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
2947 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2950 case RENDERPATH_D3D10:
2951 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2953 case RENDERPATH_D3D11:
2954 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2956 case RENDERPATH_GL20:
2957 case RENDERPATH_GLES2:
2958 R_SetupShader_SetPermutationGLSL(mode, permutation);
2959 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2960 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
2961 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);
2962 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);
2963 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);
2964 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]);
2965 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]);
2966 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));
2967 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]);
2968 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
2970 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2971 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2972 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2973 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2974 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
2975 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2977 case RENDERPATH_GL13:
2978 case RENDERPATH_GL11:
2980 case RENDERPATH_SOFT:
2981 R_SetupShader_SetPermutationGLSL(mode, permutation);
2982 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2983 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
2984 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2985 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2986 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2987 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2988 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]);
2989 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));
2990 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2991 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2993 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2994 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2995 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2996 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2997 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
2998 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3003 #define SKINFRAME_HASH 1024
3007 int loadsequence; // incremented each level change
3008 memexpandablearray_t array;
3009 skinframe_t *hash[SKINFRAME_HASH];
3012 r_skinframe_t r_skinframe;
3014 void R_SkinFrame_PrepareForPurge(void)
3016 r_skinframe.loadsequence++;
3017 // wrap it without hitting zero
3018 if (r_skinframe.loadsequence >= 200)
3019 r_skinframe.loadsequence = 1;
3022 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3026 // mark the skinframe as used for the purging code
3027 skinframe->loadsequence = r_skinframe.loadsequence;
3030 void R_SkinFrame_Purge(void)
3034 for (i = 0;i < SKINFRAME_HASH;i++)
3036 for (s = r_skinframe.hash[i];s;s = s->next)
3038 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3040 if (s->merged == s->base)
3042 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3043 R_PurgeTexture(s->stain );s->stain = NULL;
3044 R_PurgeTexture(s->merged);s->merged = NULL;
3045 R_PurgeTexture(s->base );s->base = NULL;
3046 R_PurgeTexture(s->pants );s->pants = NULL;
3047 R_PurgeTexture(s->shirt );s->shirt = NULL;
3048 R_PurgeTexture(s->nmap );s->nmap = NULL;
3049 R_PurgeTexture(s->gloss );s->gloss = NULL;
3050 R_PurgeTexture(s->glow );s->glow = NULL;
3051 R_PurgeTexture(s->fog );s->fog = NULL;
3052 R_PurgeTexture(s->reflect);s->reflect = NULL;
3053 s->loadsequence = 0;
3059 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3061 char basename[MAX_QPATH];
3063 Image_StripImageExtension(name, basename, sizeof(basename));
3065 if( last == NULL ) {
3067 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3068 item = r_skinframe.hash[hashindex];
3073 // linearly search through the hash bucket
3074 for( ; item ; item = item->next ) {
3075 if( !strcmp( item->basename, basename ) ) {
3082 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3086 char basename[MAX_QPATH];
3088 Image_StripImageExtension(name, basename, sizeof(basename));
3090 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3091 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3092 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3096 rtexture_t *dyntexture;
3097 // check whether its a dynamic texture
3098 dyntexture = CL_GetDynTexture( basename );
3099 if (!add && !dyntexture)
3101 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3102 memset(item, 0, sizeof(*item));
3103 strlcpy(item->basename, basename, sizeof(item->basename));
3104 item->base = dyntexture; // either NULL or dyntexture handle
3105 item->textureflags = textureflags;
3106 item->comparewidth = comparewidth;
3107 item->compareheight = compareheight;
3108 item->comparecrc = comparecrc;
3109 item->next = r_skinframe.hash[hashindex];
3110 r_skinframe.hash[hashindex] = item;
3112 else if( item->base == NULL )
3114 rtexture_t *dyntexture;
3115 // check whether its a dynamic texture
3116 // 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]
3117 dyntexture = CL_GetDynTexture( basename );
3118 item->base = dyntexture; // either NULL or dyntexture handle
3121 R_SkinFrame_MarkUsed(item);
3125 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3127 unsigned long long avgcolor[5], wsum; \
3135 for(pix = 0; pix < cnt; ++pix) \
3138 for(comp = 0; comp < 3; ++comp) \
3140 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3143 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3145 for(comp = 0; comp < 3; ++comp) \
3146 avgcolor[comp] += getpixel * w; \
3149 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3150 avgcolor[4] += getpixel; \
3152 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3154 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3155 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3156 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3157 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3160 extern cvar_t gl_picmip;
3161 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3164 unsigned char *pixels;
3165 unsigned char *bumppixels;
3166 unsigned char *basepixels = NULL;
3167 int basepixels_width = 0;
3168 int basepixels_height = 0;
3169 skinframe_t *skinframe;
3170 rtexture_t *ddsbase = NULL;
3171 qboolean ddshasalpha = false;
3172 float ddsavgcolor[4];
3173 char basename[MAX_QPATH];
3174 int miplevel = R_PicmipForFlags(textureflags);
3175 int savemiplevel = miplevel;
3178 if (cls.state == ca_dedicated)
3181 // return an existing skinframe if already loaded
3182 // if loading of the first image fails, don't make a new skinframe as it
3183 // would cause all future lookups of this to be missing
3184 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3185 if (skinframe && skinframe->base)
3188 Image_StripImageExtension(name, basename, sizeof(basename));
3190 // check for DDS texture file first
3191 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3193 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
3194 if (basepixels == NULL)
3198 // FIXME handle miplevel
3200 if (developer_loading.integer)
3201 Con_Printf("loading skin \"%s\"\n", name);
3203 // we've got some pixels to store, so really allocate this new texture now
3205 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3206 skinframe->stain = NULL;
3207 skinframe->merged = NULL;
3208 skinframe->base = NULL;
3209 skinframe->pants = NULL;
3210 skinframe->shirt = NULL;
3211 skinframe->nmap = NULL;
3212 skinframe->gloss = NULL;
3213 skinframe->glow = NULL;
3214 skinframe->fog = NULL;
3215 skinframe->reflect = NULL;
3216 skinframe->hasalpha = false;
3220 skinframe->base = ddsbase;
3221 skinframe->hasalpha = ddshasalpha;
3222 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3223 if (r_loadfog && skinframe->hasalpha)
3224 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3225 //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]);
3229 basepixels_width = image_width;
3230 basepixels_height = image_height;
3231 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3232 if (textureflags & TEXF_ALPHA)
3234 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3236 if (basepixels[j] < 255)
3238 skinframe->hasalpha = true;
3242 if (r_loadfog && skinframe->hasalpha)
3244 // has transparent pixels
3245 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3246 for (j = 0;j < image_width * image_height * 4;j += 4)
3251 pixels[j+3] = basepixels[j+3];
3253 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);
3257 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3258 //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]);
3259 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3260 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
3261 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3262 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
3267 mymiplevel = savemiplevel;
3268 if (r_loadnormalmap)
3269 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);
3270 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3272 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3273 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3274 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3275 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3278 // _norm is the name used by tenebrae and has been adopted as standard
3279 if (r_loadnormalmap && skinframe->nmap == NULL)
3281 mymiplevel = savemiplevel;
3282 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3284 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);
3288 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3290 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3291 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3292 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);
3294 Mem_Free(bumppixels);
3296 else if (r_shadow_bumpscale_basetexture.value > 0)
3298 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3299 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3300 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);
3303 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3304 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
3307 // _luma is supported only for tenebrae compatibility
3308 // _glow is the preferred name
3309 mymiplevel = savemiplevel;
3310 if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel))))
3312 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3313 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3314 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
3315 Mem_Free(pixels);pixels = NULL;
3318 mymiplevel = savemiplevel;
3319 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3321 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3322 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3323 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
3328 mymiplevel = savemiplevel;
3329 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3331 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3332 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3333 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
3338 mymiplevel = savemiplevel;
3339 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3341 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3342 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3343 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
3348 mymiplevel = savemiplevel;
3349 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3351 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3352 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3353 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
3359 Mem_Free(basepixels);
3364 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3365 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
3368 unsigned char *temp1, *temp2;
3369 skinframe_t *skinframe;
3371 if (cls.state == ca_dedicated)
3374 // if already loaded just return it, otherwise make a new skinframe
3375 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3376 if (skinframe && skinframe->base)
3379 skinframe->stain = NULL;
3380 skinframe->merged = NULL;
3381 skinframe->base = NULL;
3382 skinframe->pants = NULL;
3383 skinframe->shirt = NULL;
3384 skinframe->nmap = NULL;
3385 skinframe->gloss = NULL;
3386 skinframe->glow = NULL;
3387 skinframe->fog = NULL;
3388 skinframe->reflect = NULL;
3389 skinframe->hasalpha = false;
3391 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3395 if (developer_loading.integer)
3396 Con_Printf("loading 32bit skin \"%s\"\n", name);
3398 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3400 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3401 temp2 = temp1 + width * height * 4;
3402 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3403 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);
3406 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
3407 if (textureflags & TEXF_ALPHA)
3409 for (i = 3;i < width * height * 4;i += 4)
3411 if (skindata[i] < 255)
3413 skinframe->hasalpha = true;
3417 if (r_loadfog && skinframe->hasalpha)
3419 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3420 memcpy(fogpixels, skindata, width * height * 4);
3421 for (i = 0;i < width * height * 4;i += 4)
3422 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3423 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3424 Mem_Free(fogpixels);
3428 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3429 //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]);
3434 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3438 skinframe_t *skinframe;
3440 if (cls.state == ca_dedicated)
3443 // if already loaded just return it, otherwise make a new skinframe
3444 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3445 if (skinframe && skinframe->base)
3448 skinframe->stain = NULL;
3449 skinframe->merged = NULL;
3450 skinframe->base = NULL;
3451 skinframe->pants = NULL;
3452 skinframe->shirt = NULL;
3453 skinframe->nmap = NULL;
3454 skinframe->gloss = NULL;
3455 skinframe->glow = NULL;
3456 skinframe->fog = NULL;
3457 skinframe->reflect = NULL;
3458 skinframe->hasalpha = false;
3460 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3464 if (developer_loading.integer)
3465 Con_Printf("loading quake skin \"%s\"\n", name);
3467 // 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)
3468 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3469 memcpy(skinframe->qpixels, skindata, width*height);
3470 skinframe->qwidth = width;
3471 skinframe->qheight = height;
3474 for (i = 0;i < width * height;i++)
3475 featuresmask |= palette_featureflags[skindata[i]];
3477 skinframe->hasalpha = false;
3478 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3479 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3480 skinframe->qgeneratemerged = true;
3481 skinframe->qgeneratebase = skinframe->qhascolormapping;
3482 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3484 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3485 //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]);
3490 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3494 unsigned char *skindata;
3496 if (!skinframe->qpixels)
3499 if (!skinframe->qhascolormapping)
3500 colormapped = false;
3504 if (!skinframe->qgeneratebase)
3509 if (!skinframe->qgeneratemerged)
3513 width = skinframe->qwidth;
3514 height = skinframe->qheight;
3515 skindata = skinframe->qpixels;
3517 if (skinframe->qgeneratenmap)
3519 unsigned char *temp1, *temp2;
3520 skinframe->qgeneratenmap = false;
3521 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3522 temp2 = temp1 + width * height * 4;
3523 // use either a custom palette or the quake palette
3524 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3525 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3526 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);
3530 if (skinframe->qgenerateglow)
3532 skinframe->qgenerateglow = false;
3533 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3538 skinframe->qgeneratebase = false;
3539 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);
3540 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3541 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3545 skinframe->qgeneratemerged = false;
3546 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);
3549 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3551 Mem_Free(skinframe->qpixels);
3552 skinframe->qpixels = NULL;
3556 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)
3559 skinframe_t *skinframe;
3561 if (cls.state == ca_dedicated)
3564 // if already loaded just return it, otherwise make a new skinframe
3565 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3566 if (skinframe && skinframe->base)
3569 skinframe->stain = NULL;
3570 skinframe->merged = NULL;
3571 skinframe->base = NULL;
3572 skinframe->pants = NULL;
3573 skinframe->shirt = NULL;
3574 skinframe->nmap = NULL;
3575 skinframe->gloss = NULL;
3576 skinframe->glow = NULL;
3577 skinframe->fog = NULL;
3578 skinframe->reflect = NULL;
3579 skinframe->hasalpha = false;
3581 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3585 if (developer_loading.integer)
3586 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3588 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3589 if (textureflags & TEXF_ALPHA)
3591 for (i = 0;i < width * height;i++)
3593 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3595 skinframe->hasalpha = true;
3599 if (r_loadfog && skinframe->hasalpha)
3600 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3603 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3604 //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]);
3609 skinframe_t *R_SkinFrame_LoadMissing(void)
3611 skinframe_t *skinframe;
3613 if (cls.state == ca_dedicated)
3616 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3617 skinframe->stain = NULL;
3618 skinframe->merged = NULL;
3619 skinframe->base = NULL;
3620 skinframe->pants = NULL;
3621 skinframe->shirt = NULL;
3622 skinframe->nmap = NULL;
3623 skinframe->gloss = NULL;
3624 skinframe->glow = NULL;
3625 skinframe->fog = NULL;
3626 skinframe->reflect = NULL;
3627 skinframe->hasalpha = false;
3629 skinframe->avgcolor[0] = rand() / RAND_MAX;
3630 skinframe->avgcolor[1] = rand() / RAND_MAX;
3631 skinframe->avgcolor[2] = rand() / RAND_MAX;
3632 skinframe->avgcolor[3] = 1;
3637 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3638 typedef struct suffixinfo_s
3641 qboolean flipx, flipy, flipdiagonal;
3644 static suffixinfo_t suffix[3][6] =
3647 {"px", false, false, false},
3648 {"nx", false, false, false},
3649 {"py", false, false, false},
3650 {"ny", false, false, false},
3651 {"pz", false, false, false},
3652 {"nz", false, false, false}
3655 {"posx", false, false, false},
3656 {"negx", false, false, false},
3657 {"posy", false, false, false},
3658 {"negy", false, false, false},
3659 {"posz", false, false, false},
3660 {"negz", false, false, false}
3663 {"rt", true, false, true},
3664 {"lf", false, true, true},
3665 {"ft", true, true, false},
3666 {"bk", false, false, false},
3667 {"up", true, false, true},
3668 {"dn", true, false, true}
3672 static int componentorder[4] = {0, 1, 2, 3};
3674 rtexture_t *R_LoadCubemap(const char *basename)
3676 int i, j, cubemapsize;
3677 unsigned char *cubemappixels, *image_buffer;
3678 rtexture_t *cubemaptexture;
3680 // must start 0 so the first loadimagepixels has no requested width/height
3682 cubemappixels = NULL;
3683 cubemaptexture = NULL;
3684 // keep trying different suffix groups (posx, px, rt) until one loads
3685 for (j = 0;j < 3 && !cubemappixels;j++)
3687 // load the 6 images in the suffix group
3688 for (i = 0;i < 6;i++)
3690 // generate an image name based on the base and and suffix
3691 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3693 if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
3695 // an image loaded, make sure width and height are equal
3696 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3698 // if this is the first image to load successfully, allocate the cubemap memory
3699 if (!cubemappixels && image_width >= 1)
3701 cubemapsize = image_width;
3702 // note this clears to black, so unavailable sides are black
3703 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3705 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3707 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);
3710 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3712 Mem_Free(image_buffer);
3716 // if a cubemap loaded, upload it
3719 if (developer_loading.integer)
3720 Con_Printf("loading cubemap \"%s\"\n", basename);
3722 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3723 Mem_Free(cubemappixels);
3727 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3728 if (developer_loading.integer)
3730 Con_Printf("(tried tried images ");
3731 for (j = 0;j < 3;j++)
3732 for (i = 0;i < 6;i++)
3733 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3734 Con_Print(" and was unable to find any of them).\n");
3737 return cubemaptexture;
3740 rtexture_t *R_GetCubemap(const char *basename)
3743 for (i = 0;i < r_texture_numcubemaps;i++)
3744 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3745 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3746 if (i >= MAX_CUBEMAPS)
3747 return r_texture_whitecube;
3748 r_texture_numcubemaps++;
3749 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3750 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3751 return r_texture_cubemaps[i].texture;
3754 void R_FreeCubemaps(void)
3757 for (i = 0;i < r_texture_numcubemaps;i++)
3759 if (developer_loading.integer)
3760 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3761 if (r_texture_cubemaps[i].texture)
3762 R_FreeTexture(r_texture_cubemaps[i].texture);
3764 r_texture_numcubemaps = 0;
3767 void R_Main_FreeViewCache(void)
3769 if (r_refdef.viewcache.entityvisible)
3770 Mem_Free(r_refdef.viewcache.entityvisible);
3771 if (r_refdef.viewcache.world_pvsbits)
3772 Mem_Free(r_refdef.viewcache.world_pvsbits);
3773 if (r_refdef.viewcache.world_leafvisible)
3774 Mem_Free(r_refdef.viewcache.world_leafvisible);
3775 if (r_refdef.viewcache.world_surfacevisible)
3776 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3777 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3780 void R_Main_ResizeViewCache(void)
3782 int numentities = r_refdef.scene.numentities;
3783 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3784 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3785 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3786 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3787 if (r_refdef.viewcache.maxentities < numentities)
3789 r_refdef.viewcache.maxentities = numentities;
3790 if (r_refdef.viewcache.entityvisible)
3791 Mem_Free(r_refdef.viewcache.entityvisible);
3792 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3794 if (r_refdef.viewcache.world_numclusters != numclusters)
3796 r_refdef.viewcache.world_numclusters = numclusters;
3797 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3798 if (r_refdef.viewcache.world_pvsbits)
3799 Mem_Free(r_refdef.viewcache.world_pvsbits);
3800 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3802 if (r_refdef.viewcache.world_numleafs != numleafs)
3804 r_refdef.viewcache.world_numleafs = numleafs;
3805 if (r_refdef.viewcache.world_leafvisible)
3806 Mem_Free(r_refdef.viewcache.world_leafvisible);
3807 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3809 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3811 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3812 if (r_refdef.viewcache.world_surfacevisible)
3813 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3814 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3818 extern rtexture_t *loadingscreentexture;
3819 void gl_main_start(void)
3821 loadingscreentexture = NULL;
3822 r_texture_blanknormalmap = NULL;
3823 r_texture_white = NULL;
3824 r_texture_grey128 = NULL;
3825 r_texture_black = NULL;
3826 r_texture_whitecube = NULL;
3827 r_texture_normalizationcube = NULL;
3828 r_texture_fogattenuation = NULL;
3829 r_texture_fogheighttexture = NULL;
3830 r_texture_gammaramps = NULL;
3831 r_texture_numcubemaps = 0;
3833 r_loaddds = r_texture_dds_load.integer != 0;
3834 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3836 switch(vid.renderpath)
3838 case RENDERPATH_GL20:
3839 case RENDERPATH_D3D9:
3840 case RENDERPATH_D3D10:
3841 case RENDERPATH_D3D11:
3842 case RENDERPATH_SOFT:
3843 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3844 Cvar_SetValueQuick(&gl_combine, 1);
3845 Cvar_SetValueQuick(&r_glsl, 1);
3846 r_loadnormalmap = true;
3850 case RENDERPATH_GL13:
3851 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3852 Cvar_SetValueQuick(&gl_combine, 1);
3853 Cvar_SetValueQuick(&r_glsl, 0);
3854 r_loadnormalmap = false;
3855 r_loadgloss = false;
3858 case RENDERPATH_GL11:
3859 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3860 Cvar_SetValueQuick(&gl_combine, 0);
3861 Cvar_SetValueQuick(&r_glsl, 0);
3862 r_loadnormalmap = false;
3863 r_loadgloss = false;
3866 case RENDERPATH_GLES2:
3867 Cvar_SetValueQuick(&r_textureunits, 1);
3868 Cvar_SetValueQuick(&gl_combine, 1);
3869 Cvar_SetValueQuick(&r_glsl, 1);
3870 r_loadnormalmap = true;
3871 r_loadgloss = false;
3877 R_FrameData_Reset();
3881 memset(r_queries, 0, sizeof(r_queries));
3883 r_qwskincache = NULL;
3884 r_qwskincache_size = 0;
3886 // due to caching of texture_t references, the collision cache must be reset
3887 Collision_Cache_Reset(true);
3889 // set up r_skinframe loading system for textures
3890 memset(&r_skinframe, 0, sizeof(r_skinframe));
3891 r_skinframe.loadsequence = 1;
3892 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3894 r_main_texturepool = R_AllocTexturePool();
3895 R_BuildBlankTextures();
3897 if (vid.support.arb_texture_cube_map)
3900 R_BuildNormalizationCube();
3902 r_texture_fogattenuation = NULL;
3903 r_texture_fogheighttexture = NULL;
3904 r_texture_gammaramps = NULL;
3905 //r_texture_fogintensity = NULL;
3906 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3907 memset(&r_waterstate, 0, sizeof(r_waterstate));
3908 r_glsl_permutation = NULL;
3909 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3910 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3911 glslshaderstring = NULL;
3913 r_hlsl_permutation = NULL;
3914 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3915 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3917 hlslshaderstring = NULL;
3918 memset(&r_svbsp, 0, sizeof (r_svbsp));
3920 r_refdef.fogmasktable_density = 0;
3923 void gl_main_shutdown(void)
3926 R_FrameData_Reset();
3928 R_Main_FreeViewCache();
3930 switch(vid.renderpath)
3932 case RENDERPATH_GL11:
3933 case RENDERPATH_GL13:
3934 case RENDERPATH_GL20:
3935 case RENDERPATH_GLES2:
3937 qglDeleteQueriesARB(r_maxqueries, r_queries);
3939 case RENDERPATH_D3D9:
3940 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3942 case RENDERPATH_D3D10:
3943 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3945 case RENDERPATH_D3D11:
3946 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3948 case RENDERPATH_SOFT:
3954 memset(r_queries, 0, sizeof(r_queries));
3956 r_qwskincache = NULL;
3957 r_qwskincache_size = 0;
3959 // clear out the r_skinframe state
3960 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3961 memset(&r_skinframe, 0, sizeof(r_skinframe));
3964 Mem_Free(r_svbsp.nodes);
3965 memset(&r_svbsp, 0, sizeof (r_svbsp));
3966 R_FreeTexturePool(&r_main_texturepool);
3967 loadingscreentexture = NULL;
3968 r_texture_blanknormalmap = NULL;
3969 r_texture_white = NULL;
3970 r_texture_grey128 = NULL;
3971 r_texture_black = NULL;
3972 r_texture_whitecube = NULL;
3973 r_texture_normalizationcube = NULL;
3974 r_texture_fogattenuation = NULL;
3975 r_texture_fogheighttexture = NULL;
3976 r_texture_gammaramps = NULL;
3977 r_texture_numcubemaps = 0;
3978 //r_texture_fogintensity = NULL;
3979 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3980 memset(&r_waterstate, 0, sizeof(r_waterstate));
3983 r_glsl_permutation = NULL;
3984 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3985 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3986 glslshaderstring = NULL;
3988 r_hlsl_permutation = NULL;
3989 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3990 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3992 hlslshaderstring = NULL;
3995 extern void CL_ParseEntityLump(char *entitystring);
3996 void gl_main_newmap(void)
3998 // FIXME: move this code to client
3999 char *entities, entname[MAX_QPATH];
4001 Mem_Free(r_qwskincache);
4002 r_qwskincache = NULL;
4003 r_qwskincache_size = 0;
4006 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4007 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4009 CL_ParseEntityLump(entities);
4013 if (cl.worldmodel->brush.entities)
4014 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4016 R_Main_FreeViewCache();
4018 R_FrameData_Reset();
4021 void GL_Main_Init(void)
4023 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4025 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4026 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4027 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4028 if (gamemode == GAME_NEHAHRA)
4030 Cvar_RegisterVariable (&gl_fogenable);
4031 Cvar_RegisterVariable (&gl_fogdensity);
4032 Cvar_RegisterVariable (&gl_fogred);
4033 Cvar_RegisterVariable (&gl_foggreen);
4034 Cvar_RegisterVariable (&gl_fogblue);
4035 Cvar_RegisterVariable (&gl_fogstart);
4036 Cvar_RegisterVariable (&gl_fogend);
4037 Cvar_RegisterVariable (&gl_skyclip);
4039 Cvar_RegisterVariable(&r_motionblur);
4040 Cvar_RegisterVariable(&r_motionblur_maxblur);
4041 Cvar_RegisterVariable(&r_motionblur_bmin);
4042 Cvar_RegisterVariable(&r_motionblur_vmin);
4043 Cvar_RegisterVariable(&r_motionblur_vmax);
4044 Cvar_RegisterVariable(&r_motionblur_vcoeff);
4045 Cvar_RegisterVariable(&r_motionblur_randomize);
4046 Cvar_RegisterVariable(&r_damageblur);
4047 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4048 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4049 Cvar_RegisterVariable(&r_equalize_entities_by);
4050 Cvar_RegisterVariable(&r_equalize_entities_to);
4051 Cvar_RegisterVariable(&r_depthfirst);
4052 Cvar_RegisterVariable(&r_useinfinitefarclip);
4053 Cvar_RegisterVariable(&r_farclip_base);
4054 Cvar_RegisterVariable(&r_farclip_world);
4055 Cvar_RegisterVariable(&r_nearclip);
4056 Cvar_RegisterVariable(&r_showbboxes);
4057 Cvar_RegisterVariable(&r_showsurfaces);
4058 Cvar_RegisterVariable(&r_showtris);
4059 Cvar_RegisterVariable(&r_shownormals);
4060 Cvar_RegisterVariable(&r_showlighting);
4061 Cvar_RegisterVariable(&r_showshadowvolumes);
4062 Cvar_RegisterVariable(&r_showcollisionbrushes);
4063 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4064 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4065 Cvar_RegisterVariable(&r_showdisabledepthtest);
4066 Cvar_RegisterVariable(&r_drawportals);
4067 Cvar_RegisterVariable(&r_drawentities);
4068 Cvar_RegisterVariable(&r_draw2d);
4069 Cvar_RegisterVariable(&r_drawworld);
4070 Cvar_RegisterVariable(&r_cullentities_trace);
4071 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4072 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4073 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4074 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4075 Cvar_RegisterVariable(&r_drawviewmodel);
4076 Cvar_RegisterVariable(&r_drawexteriormodel);
4077 Cvar_RegisterVariable(&r_speeds);
4078 Cvar_RegisterVariable(&r_fullbrights);
4079 Cvar_RegisterVariable(&r_wateralpha);
4080 Cvar_RegisterVariable(&r_dynamic);
4081 Cvar_RegisterVariable(&r_fakelight);
4082 Cvar_RegisterVariable(&r_fakelight_intensity);
4083 Cvar_RegisterVariable(&r_fullbright);
4084 Cvar_RegisterVariable(&r_shadows);
4085 Cvar_RegisterVariable(&r_shadows_darken);
4086 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4087 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4088 Cvar_RegisterVariable(&r_shadows_throwdistance);
4089 Cvar_RegisterVariable(&r_shadows_throwdirection);
4090 Cvar_RegisterVariable(&r_shadows_focus);
4091 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4092 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4093 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4094 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4095 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4096 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4097 Cvar_RegisterVariable(&r_fog_exp2);
4098 Cvar_RegisterVariable(&r_fog_clear);
4099 Cvar_RegisterVariable(&r_drawfog);
4100 Cvar_RegisterVariable(&r_transparentdepthmasking);
4101 Cvar_RegisterVariable(&r_texture_dds_load);
4102 Cvar_RegisterVariable(&r_texture_dds_save);
4103 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
4104 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
4105 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
4106 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
4107 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
4108 Cvar_RegisterVariable(&r_textureunits);
4109 Cvar_RegisterVariable(&gl_combine);
4110 Cvar_RegisterVariable(&r_viewfbo);
4111 Cvar_RegisterVariable(&r_viewscale);
4112 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4113 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4114 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4115 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4116 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4117 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4118 Cvar_RegisterVariable(&r_glsl);
4119 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4120 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4121 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4122 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4123 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4124 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4125 Cvar_RegisterVariable(&r_glsl_postprocess);
4126 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4127 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4128 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4129 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4130 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4131 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4132 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4133 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4135 Cvar_RegisterVariable(&r_water);
4136 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4137 Cvar_RegisterVariable(&r_water_clippingplanebias);
4138 Cvar_RegisterVariable(&r_water_refractdistort);
4139 Cvar_RegisterVariable(&r_water_reflectdistort);
4140 Cvar_RegisterVariable(&r_water_scissormode);
4141 Cvar_RegisterVariable(&r_lerpsprites);
4142 Cvar_RegisterVariable(&r_lerpmodels);
4143 Cvar_RegisterVariable(&r_lerplightstyles);
4144 Cvar_RegisterVariable(&r_waterscroll);
4145 Cvar_RegisterVariable(&r_bloom);
4146 Cvar_RegisterVariable(&r_bloom_colorscale);
4147 Cvar_RegisterVariable(&r_bloom_brighten);
4148 Cvar_RegisterVariable(&r_bloom_blur);
4149 Cvar_RegisterVariable(&r_bloom_resolution);
4150 Cvar_RegisterVariable(&r_bloom_colorexponent);
4151 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4152 Cvar_RegisterVariable(&r_hdr);
4153 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4154 Cvar_RegisterVariable(&r_hdr_glowintensity);
4155 Cvar_RegisterVariable(&r_hdr_range);
4156 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4157 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4158 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4159 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4160 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4161 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4162 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4163 Cvar_RegisterVariable(&developer_texturelogging);
4164 Cvar_RegisterVariable(&gl_lightmaps);
4165 Cvar_RegisterVariable(&r_test);
4166 Cvar_RegisterVariable(&r_glsl_saturation);
4167 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4168 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4169 Cvar_RegisterVariable(&r_framedatasize);
4170 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4171 Cvar_SetValue("r_fullbrights", 0);
4172 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4174 Cvar_RegisterVariable(&r_track_sprites);
4175 Cvar_RegisterVariable(&r_track_sprites_flags);
4176 Cvar_RegisterVariable(&r_track_sprites_scalew);
4177 Cvar_RegisterVariable(&r_track_sprites_scaleh);
4178 Cvar_RegisterVariable(&r_overheadsprites_perspective);
4179 Cvar_RegisterVariable(&r_overheadsprites_pushback);
4180 Cvar_RegisterVariable(&r_overheadsprites_scalex);
4181 Cvar_RegisterVariable(&r_overheadsprites_scaley);
4184 extern void R_Textures_Init(void);
4185 extern void GL_Draw_Init(void);
4186 extern void GL_Main_Init(void);
4187 extern void R_Shadow_Init(void);
4188 extern void R_Sky_Init(void);
4189 extern void GL_Surf_Init(void);
4190 extern void R_Particles_Init(void);
4191 extern void R_Explosion_Init(void);
4192 extern void gl_backend_init(void);
4193 extern void Sbar_Init(void);
4194 extern void R_LightningBeams_Init(void);
4195 extern void Mod_RenderInit(void);
4196 extern void Font_Init(void);
4198 void Render_Init(void)
4211 R_LightningBeams_Init();
4220 extern char *ENGINE_EXTENSIONS;
4223 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4224 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4225 gl_version = (const char *)qglGetString(GL_VERSION);
4226 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4230 if (!gl_platformextensions)
4231 gl_platformextensions = "";
4233 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4234 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4235 Con_Printf("GL_VERSION: %s\n", gl_version);
4236 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4237 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4239 VID_CheckExtensions();
4241 // LordHavoc: report supported extensions
4242 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4244 // clear to black (loading plaque will be seen over this)
4245 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4248 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4252 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4254 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4257 p = r_refdef.view.frustum + i;
4262 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4266 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4270 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4274 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4278 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4282 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4286 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4290 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4298 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4302 for (i = 0;i < numplanes;i++)
4309 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4313 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4317 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4321 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4325 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4329 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4333 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4337 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4345 //==================================================================================
4347 // LordHavoc: this stores temporary data used within the same frame
4349 typedef struct r_framedata_mem_s
4351 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4352 size_t size; // how much usable space
4353 size_t current; // how much space in use
4354 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4355 size_t wantedsize; // how much space was allocated
4356 unsigned char *data; // start of real data (16byte aligned)
4360 static r_framedata_mem_t *r_framedata_mem;
4362 void R_FrameData_Reset(void)
4364 while (r_framedata_mem)
4366 r_framedata_mem_t *next = r_framedata_mem->purge;
4367 Mem_Free(r_framedata_mem);
4368 r_framedata_mem = next;
4372 void R_FrameData_Resize(void)
4375 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4376 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4377 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4379 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4380 newmem->wantedsize = wantedsize;
4381 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4382 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4383 newmem->current = 0;
4385 newmem->purge = r_framedata_mem;
4386 r_framedata_mem = newmem;
4390 void R_FrameData_NewFrame(void)
4392 R_FrameData_Resize();
4393 if (!r_framedata_mem)
4395 // if we ran out of space on the last frame, free the old memory now
4396 while (r_framedata_mem->purge)
4398 // repeatedly remove the second item in the list, leaving only head
4399 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4400 Mem_Free(r_framedata_mem->purge);
4401 r_framedata_mem->purge = next;
4403 // reset the current mem pointer
4404 r_framedata_mem->current = 0;
4405 r_framedata_mem->mark = 0;
4408 void *R_FrameData_Alloc(size_t size)
4412 // align to 16 byte boundary - the data pointer is already aligned, so we
4413 // only need to ensure the size of every allocation is also aligned
4414 size = (size + 15) & ~15;
4416 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4418 // emergency - we ran out of space, allocate more memory
4419 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4420 R_FrameData_Resize();
4423 data = r_framedata_mem->data + r_framedata_mem->current;
4424 r_framedata_mem->current += size;
4426 // count the usage for stats
4427 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4428 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4430 return (void *)data;
4433 void *R_FrameData_Store(size_t size, void *data)
4435 void *d = R_FrameData_Alloc(size);
4437 memcpy(d, data, size);
4441 void R_FrameData_SetMark(void)
4443 if (!r_framedata_mem)
4445 r_framedata_mem->mark = r_framedata_mem->current;
4448 void R_FrameData_ReturnToMark(void)
4450 if (!r_framedata_mem)
4452 r_framedata_mem->current = r_framedata_mem->mark;
4455 //==================================================================================
4457 // LordHavoc: animcache originally written by Echon, rewritten since then
4460 * Animation cache prevents re-generating mesh data for an animated model
4461 * multiple times in one frame for lighting, shadowing, reflections, etc.
4464 void R_AnimCache_Free(void)
4468 void R_AnimCache_ClearCache(void)
4471 entity_render_t *ent;
4473 for (i = 0;i < r_refdef.scene.numentities;i++)
4475 ent = r_refdef.scene.entities[i];
4476 ent->animcache_vertex3f = NULL;
4477 ent->animcache_normal3f = NULL;
4478 ent->animcache_svector3f = NULL;
4479 ent->animcache_tvector3f = NULL;
4480 ent->animcache_vertexmesh = NULL;
4481 ent->animcache_vertex3fbuffer = NULL;
4482 ent->animcache_vertexmeshbuffer = NULL;
4486 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4490 // check if we need the meshbuffers
4491 if (!vid.useinterleavedarrays)
4494 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4495 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4496 // TODO: upload vertex3f buffer?
4497 if (ent->animcache_vertexmesh)
4499 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4500 for (i = 0;i < numvertices;i++)
4501 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4502 if (ent->animcache_svector3f)
4503 for (i = 0;i < numvertices;i++)
4504 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4505 if (ent->animcache_tvector3f)
4506 for (i = 0;i < numvertices;i++)
4507 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4508 if (ent->animcache_normal3f)
4509 for (i = 0;i < numvertices;i++)
4510 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4511 // TODO: upload vertexmeshbuffer?
4515 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4517 dp_model_t *model = ent->model;
4519 // see if it's already cached this frame
4520 if (ent->animcache_vertex3f)
4522 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4523 if (wantnormals || wanttangents)
4525 if (ent->animcache_normal3f)
4526 wantnormals = false;
4527 if (ent->animcache_svector3f)
4528 wanttangents = false;
4529 if (wantnormals || wanttangents)
4531 numvertices = model->surfmesh.num_vertices;
4533 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4536 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4537 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4539 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4540 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4546 // see if this ent is worth caching
4547 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4549 // get some memory for this entity and generate mesh data
4550 numvertices = model->surfmesh.num_vertices;
4551 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4553 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4556 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4557 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4559 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4560 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4565 void R_AnimCache_CacheVisibleEntities(void)
4568 qboolean wantnormals = true;
4569 qboolean wanttangents = !r_showsurfaces.integer;
4571 switch(vid.renderpath)
4573 case RENDERPATH_GL20:
4574 case RENDERPATH_D3D9:
4575 case RENDERPATH_D3D10:
4576 case RENDERPATH_D3D11:
4577 case RENDERPATH_GLES2:
4579 case RENDERPATH_GL13:
4580 case RENDERPATH_GL11:
4581 wanttangents = false;
4583 case RENDERPATH_SOFT:
4587 if (r_shownormals.integer)
4588 wanttangents = wantnormals = true;
4590 // TODO: thread this
4591 // NOTE: R_PrepareRTLights() also caches entities
4593 for (i = 0;i < r_refdef.scene.numentities;i++)
4594 if (r_refdef.viewcache.entityvisible[i])
4595 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4598 //==================================================================================
4600 static void R_View_UpdateEntityLighting (void)
4603 entity_render_t *ent;
4604 vec3_t tempdiffusenormal, avg;
4605 vec_t f, fa, fd, fdd;
4606 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4608 for (i = 0;i < r_refdef.scene.numentities;i++)
4610 ent = r_refdef.scene.entities[i];
4612 // skip unseen models
4613 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4617 if (ent->model && ent->model->brush.num_leafs)
4619 // TODO: use modellight for r_ambient settings on world?
4620 VectorSet(ent->modellight_ambient, 0, 0, 0);
4621 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4622 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4626 // fetch the lighting from the worldmodel data
4627 VectorClear(ent->modellight_ambient);
4628 VectorClear(ent->modellight_diffuse);
4629 VectorClear(tempdiffusenormal);
4630 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4633 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4635 // complete lightning for lit sprites
4636 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4637 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4639 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4640 org[2] = org[2] + r_overheadsprites_pushback.value;
4641 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4644 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4646 if(ent->flags & RENDER_EQUALIZE)
4648 // first fix up ambient lighting...
4649 if(r_equalize_entities_minambient.value > 0)
4651 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4654 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4655 if(fa < r_equalize_entities_minambient.value * fd)
4658 // fa'/fd' = minambient
4659 // fa'+0.25*fd' = fa+0.25*fd
4661 // fa' = fd' * minambient
4662 // fd'*(0.25+minambient) = fa+0.25*fd
4664 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4665 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4667 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4668 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
4669 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4670 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4675 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4677 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4678 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4682 // adjust brightness and saturation to target
4683 avg[0] = avg[1] = avg[2] = fa / f;
4684 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4685 avg[0] = avg[1] = avg[2] = fd / f;
4686 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4692 VectorSet(ent->modellight_ambient, 1, 1, 1);
4694 // move the light direction into modelspace coordinates for lighting code
4695 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4696 if(VectorLength2(ent->modellight_lightdir) == 0)
4697 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4698 VectorNormalize(ent->modellight_lightdir);
4702 #define MAX_LINEOFSIGHTTRACES 64
4704 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4707 vec3_t boxmins, boxmaxs;
4710 dp_model_t *model = r_refdef.scene.worldmodel;
4712 if (!model || !model->brush.TraceLineOfSight)
4715 // expand the box a little
4716 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4717 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4718 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4719 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4720 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4721 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4723 // return true if eye is inside enlarged box
4724 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4728 VectorCopy(eye, start);
4729 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4730 if (model->brush.TraceLineOfSight(model, start, end))
4733 // try various random positions
4734 for (i = 0;i < numsamples;i++)
4736 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4737 if (model->brush.TraceLineOfSight(model, start, end))
4745 static void R_View_UpdateEntityVisible (void)
4750 entity_render_t *ent;
4752 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4753 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4754 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
4755 : RENDER_EXTERIORMODEL;
4756 if (!r_drawviewmodel.integer)
4757 renderimask |= RENDER_VIEWMODEL;
4758 if (!r_drawexteriormodel.integer)
4759 renderimask |= RENDER_EXTERIORMODEL;
4760 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4762 // worldmodel can check visibility
4763 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4764 for (i = 0;i < r_refdef.scene.numentities;i++)
4766 ent = r_refdef.scene.entities[i];
4767 if (!(ent->flags & renderimask))
4768 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)))
4769 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))
4770 r_refdef.viewcache.entityvisible[i] = true;
4772 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4773 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4775 for (i = 0;i < r_refdef.scene.numentities;i++)
4777 ent = r_refdef.scene.entities[i];
4778 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4780 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4782 continue; // temp entities do pvs only
4783 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4784 ent->last_trace_visibility = realtime;
4785 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4786 r_refdef.viewcache.entityvisible[i] = 0;
4793 // no worldmodel or it can't check visibility
4794 for (i = 0;i < r_refdef.scene.numentities;i++)
4796 ent = r_refdef.scene.entities[i];
4797 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));
4802 /// only used if skyrendermasked, and normally returns false
4803 int R_DrawBrushModelsSky (void)
4806 entity_render_t *ent;
4809 for (i = 0;i < r_refdef.scene.numentities;i++)
4811 if (!r_refdef.viewcache.entityvisible[i])
4813 ent = r_refdef.scene.entities[i];
4814 if (!ent->model || !ent->model->DrawSky)
4816 ent->model->DrawSky(ent);
4822 static void R_DrawNoModel(entity_render_t *ent);
4823 static void R_DrawModels(void)
4826 entity_render_t *ent;
4828 for (i = 0;i < r_refdef.scene.numentities;i++)
4830 if (!r_refdef.viewcache.entityvisible[i])
4832 ent = r_refdef.scene.entities[i];
4833 r_refdef.stats.entities++;
4834 if (ent->model && ent->model->Draw != NULL)
4835 ent->model->Draw(ent);
4841 static void R_DrawModelsDepth(void)
4844 entity_render_t *ent;
4846 for (i = 0;i < r_refdef.scene.numentities;i++)
4848 if (!r_refdef.viewcache.entityvisible[i])
4850 ent = r_refdef.scene.entities[i];
4851 if (ent->model && ent->model->DrawDepth != NULL)
4852 ent->model->DrawDepth(ent);
4856 static void R_DrawModelsDebug(void)
4859 entity_render_t *ent;
4861 for (i = 0;i < r_refdef.scene.numentities;i++)
4863 if (!r_refdef.viewcache.entityvisible[i])
4865 ent = r_refdef.scene.entities[i];
4866 if (ent->model && ent->model->DrawDebug != NULL)
4867 ent->model->DrawDebug(ent);
4871 static void R_DrawModelsAddWaterPlanes(void)
4874 entity_render_t *ent;
4876 for (i = 0;i < r_refdef.scene.numentities;i++)
4878 if (!r_refdef.viewcache.entityvisible[i])
4880 ent = r_refdef.scene.entities[i];
4881 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4882 ent->model->DrawAddWaterPlanes(ent);
4886 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4888 if (r_hdr_irisadaptation.integer)
4892 vec3_t diffusenormal;
4897 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4898 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4899 brightness = max(0.0000001f, brightness);
4900 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4901 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4902 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4903 current = r_hdr_irisadaptation_value.value;
4905 current = min(current + adjust, goal);
4906 else if (current > goal)
4907 current = max(current - adjust, goal);
4908 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4909 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4911 else if (r_hdr_irisadaptation_value.value != 1.0f)
4912 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4915 static void R_View_SetFrustum(const int *scissor)
4918 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4919 vec3_t forward, left, up, origin, v;
4923 // flipped x coordinates (because x points left here)
4924 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4925 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4927 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4928 switch(vid.renderpath)
4930 case RENDERPATH_D3D9:
4931 case RENDERPATH_D3D10:
4932 case RENDERPATH_D3D11:
4933 case RENDERPATH_SOFT:
4934 // non-flipped y coordinates
4935 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4936 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4938 case RENDERPATH_GL11:
4939 case RENDERPATH_GL13:
4940 case RENDERPATH_GL20:
4941 case RENDERPATH_GLES2:
4942 // non-flipped y coordinates
4943 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4944 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4949 // we can't trust r_refdef.view.forward and friends in reflected scenes
4950 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4953 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4954 r_refdef.view.frustum[0].normal[1] = 0 - 0;
4955 r_refdef.view.frustum[0].normal[2] = -1 - 0;
4956 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4957 r_refdef.view.frustum[1].normal[1] = 0 + 0;
4958 r_refdef.view.frustum[1].normal[2] = -1 + 0;
4959 r_refdef.view.frustum[2].normal[0] = 0 - 0;
4960 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4961 r_refdef.view.frustum[2].normal[2] = -1 - 0;
4962 r_refdef.view.frustum[3].normal[0] = 0 + 0;
4963 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4964 r_refdef.view.frustum[3].normal[2] = -1 + 0;
4968 zNear = r_refdef.nearclip;
4969 nudge = 1.0 - 1.0 / (1<<23);
4970 r_refdef.view.frustum[4].normal[0] = 0 - 0;
4971 r_refdef.view.frustum[4].normal[1] = 0 - 0;
4972 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4973 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4974 r_refdef.view.frustum[5].normal[0] = 0 + 0;
4975 r_refdef.view.frustum[5].normal[1] = 0 + 0;
4976 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4977 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4983 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4984 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4985 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4986 r_refdef.view.frustum[0].dist = m[15] - m[12];
4988 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4989 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4990 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4991 r_refdef.view.frustum[1].dist = m[15] + m[12];
4993 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4994 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4995 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4996 r_refdef.view.frustum[2].dist = m[15] - m[13];
4998 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4999 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5000 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5001 r_refdef.view.frustum[3].dist = m[15] + m[13];
5003 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5004 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5005 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5006 r_refdef.view.frustum[4].dist = m[15] - m[14];
5008 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5009 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5010 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5011 r_refdef.view.frustum[5].dist = m[15] + m[14];
5014 if (r_refdef.view.useperspective)
5016 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5017 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]);
5018 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]);
5019 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]);
5020 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]);
5022 // then the normals from the corners relative to origin
5023 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5024 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5025 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5026 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5028 // in a NORMAL view, forward cross left == up
5029 // in a REFLECTED view, forward cross left == down
5030 // so our cross products above need to be adjusted for a left handed coordinate system
5031 CrossProduct(forward, left, v);
5032 if(DotProduct(v, up) < 0)
5034 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5035 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5036 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5037 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5040 // Leaving those out was a mistake, those were in the old code, and they
5041 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5042 // I couldn't reproduce it after adding those normalizations. --blub
5043 VectorNormalize(r_refdef.view.frustum[0].normal);
5044 VectorNormalize(r_refdef.view.frustum[1].normal);
5045 VectorNormalize(r_refdef.view.frustum[2].normal);
5046 VectorNormalize(r_refdef.view.frustum[3].normal);
5048 // make the corners absolute
5049 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5050 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5051 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5052 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5055 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5057 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5058 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5059 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5060 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5061 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5065 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5066 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5067 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5068 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5069 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5070 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5071 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5072 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5073 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5074 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5076 r_refdef.view.numfrustumplanes = 5;
5078 if (r_refdef.view.useclipplane)
5080 r_refdef.view.numfrustumplanes = 6;
5081 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5084 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5085 PlaneClassify(r_refdef.view.frustum + i);
5087 // LordHavoc: note to all quake engine coders, Quake had a special case
5088 // for 90 degrees which assumed a square view (wrong), so I removed it,
5089 // Quake2 has it disabled as well.
5091 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5092 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5093 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5094 //PlaneClassify(&frustum[0]);
5096 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5097 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5098 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5099 //PlaneClassify(&frustum[1]);
5101 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5102 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5103 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5104 //PlaneClassify(&frustum[2]);
5106 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5107 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5108 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5109 //PlaneClassify(&frustum[3]);
5112 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5113 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5114 //PlaneClassify(&frustum[4]);
5117 void R_View_UpdateWithScissor(const int *myscissor)
5119 R_Main_ResizeViewCache();
5120 R_View_SetFrustum(myscissor);
5121 R_View_WorldVisibility(r_refdef.view.useclipplane);
5122 R_View_UpdateEntityVisible();
5123 R_View_UpdateEntityLighting();
5126 void R_View_Update(void)
5128 R_Main_ResizeViewCache();
5129 R_View_SetFrustum(NULL);
5130 R_View_WorldVisibility(r_refdef.view.useclipplane);
5131 R_View_UpdateEntityVisible();
5132 R_View_UpdateEntityLighting();
5135 float viewscalefpsadjusted = 1.0f;
5137 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5139 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5140 scale = bound(0.03125f, scale, 1.0f);
5141 *outwidth = (int)ceil(width * scale);
5142 *outheight = (int)ceil(height * scale);
5145 void R_Mesh_SetMainRenderTargets(void)
5147 if (r_bloomstate.fbo_framebuffer)
5148 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5150 R_Mesh_ResetRenderTargets();
5153 void R_SetupView(qboolean allowwaterclippingplane)
5155 const float *customclipplane = NULL;
5157 int scaledwidth, scaledheight;
5158 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5160 // LordHavoc: couldn't figure out how to make this approach the
5161 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5162 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5163 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5164 dist = r_refdef.view.clipplane.dist;
5165 plane[0] = r_refdef.view.clipplane.normal[0];
5166 plane[1] = r_refdef.view.clipplane.normal[1];
5167 plane[2] = r_refdef.view.clipplane.normal[2];
5169 customclipplane = plane;
5172 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5173 if (!r_refdef.view.useperspective)
5174 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);
5175 else if (vid.stencil && r_useinfinitefarclip.integer)
5176 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);
5178 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);
5179 R_Mesh_SetMainRenderTargets();
5180 R_SetViewport(&r_refdef.view.viewport);
5183 void R_EntityMatrix(const matrix4x4_t *matrix)
5185 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5187 gl_modelmatrixchanged = false;
5188 gl_modelmatrix = *matrix;
5189 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5190 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5191 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5192 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5194 switch(vid.renderpath)
5196 case RENDERPATH_D3D9:
5198 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5199 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5202 case RENDERPATH_D3D10:
5203 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5205 case RENDERPATH_D3D11:
5206 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5208 case RENDERPATH_GL13:
5209 case RENDERPATH_GL11:
5210 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5212 case RENDERPATH_SOFT:
5213 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5214 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5216 case RENDERPATH_GL20:
5217 case RENDERPATH_GLES2:
5218 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5219 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5225 void R_ResetViewRendering2D(void)
5227 r_viewport_t viewport;
5230 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5231 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);
5232 R_Mesh_ResetRenderTargets();
5233 R_SetViewport(&viewport);
5234 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5235 GL_Color(1, 1, 1, 1);
5236 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5237 GL_BlendFunc(GL_ONE, GL_ZERO);
5238 GL_ScissorTest(false);
5239 GL_DepthMask(false);
5240 GL_DepthRange(0, 1);
5241 GL_DepthTest(false);
5242 GL_DepthFunc(GL_LEQUAL);
5243 R_EntityMatrix(&identitymatrix);
5244 R_Mesh_ResetTextureState();
5245 GL_PolygonOffset(0, 0);
5246 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5247 switch(vid.renderpath)
5249 case RENDERPATH_GL11:
5250 case RENDERPATH_GL13:
5251 case RENDERPATH_GL20:
5252 case RENDERPATH_GLES2:
5253 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5255 case RENDERPATH_D3D9:
5256 case RENDERPATH_D3D10:
5257 case RENDERPATH_D3D11:
5258 case RENDERPATH_SOFT:
5261 GL_CullFace(GL_NONE);
5264 void R_ResetViewRendering3D(void)
5269 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5270 GL_Color(1, 1, 1, 1);
5271 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5272 GL_BlendFunc(GL_ONE, GL_ZERO);
5273 GL_ScissorTest(true);
5275 GL_DepthRange(0, 1);
5277 GL_DepthFunc(GL_LEQUAL);
5278 R_EntityMatrix(&identitymatrix);
5279 R_Mesh_ResetTextureState();
5280 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5281 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5282 switch(vid.renderpath)
5284 case RENDERPATH_GL11:
5285 case RENDERPATH_GL13:
5286 case RENDERPATH_GL20:
5287 case RENDERPATH_GLES2:
5288 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5290 case RENDERPATH_D3D9:
5291 case RENDERPATH_D3D10:
5292 case RENDERPATH_D3D11:
5293 case RENDERPATH_SOFT:
5296 GL_CullFace(r_refdef.view.cullface_back);
5301 R_RenderView_UpdateViewVectors
5304 static void R_RenderView_UpdateViewVectors(void)
5306 // break apart the view matrix into vectors for various purposes
5307 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5308 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5309 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5310 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5311 // make an inverted copy of the view matrix for tracking sprites
5312 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5315 void R_RenderScene(void);
5316 void R_RenderWaterPlanes(void);
5318 static void R_Water_StartFrame(void)
5321 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5322 r_waterstate_waterplane_t *p;
5324 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5327 switch(vid.renderpath)
5329 case RENDERPATH_GL20:
5330 case RENDERPATH_D3D9:
5331 case RENDERPATH_D3D10:
5332 case RENDERPATH_D3D11:
5333 case RENDERPATH_SOFT:
5334 case RENDERPATH_GLES2:
5336 case RENDERPATH_GL13:
5337 case RENDERPATH_GL11:
5341 // set waterwidth and waterheight to the water resolution that will be
5342 // used (often less than the screen resolution for faster rendering)
5343 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5344 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5346 // calculate desired texture sizes
5347 // can't use water if the card does not support the texture size
5348 if (!r_water.integer || r_showsurfaces.integer)
5349 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5350 else if (vid.support.arb_texture_non_power_of_two)
5352 texturewidth = waterwidth;
5353 textureheight = waterheight;
5354 camerawidth = waterwidth;
5355 cameraheight = waterheight;
5359 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5360 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5361 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5362 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5365 // allocate textures as needed
5366 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5368 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5369 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5371 if (p->texture_refraction)
5372 R_FreeTexture(p->texture_refraction);
5373 p->texture_refraction = NULL;
5374 if (p->texture_reflection)
5375 R_FreeTexture(p->texture_reflection);
5376 p->texture_reflection = NULL;
5377 if (p->texture_camera)
5378 R_FreeTexture(p->texture_camera);
5379 p->texture_camera = NULL;
5381 memset(&r_waterstate, 0, sizeof(r_waterstate));
5382 r_waterstate.texturewidth = texturewidth;
5383 r_waterstate.textureheight = textureheight;
5384 r_waterstate.camerawidth = camerawidth;
5385 r_waterstate.cameraheight = cameraheight;
5388 if (r_waterstate.texturewidth)
5390 r_waterstate.enabled = true;
5392 // when doing a reduced render (HDR) we want to use a smaller area
5393 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5394 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5396 // set up variables that will be used in shader setup
5397 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5398 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5399 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5400 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5403 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5404 r_waterstate.numwaterplanes = 0;
5407 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5409 int triangleindex, planeindex;
5415 r_waterstate_waterplane_t *p;
5416 texture_t *t = R_GetCurrentTexture(surface->texture);
5418 // just use the first triangle with a valid normal for any decisions
5419 VectorClear(normal);
5420 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5422 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5423 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5424 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5425 TriangleNormal(vert[0], vert[1], vert[2], normal);
5426 if (VectorLength2(normal) >= 0.001)
5430 VectorCopy(normal, plane.normal);
5431 VectorNormalize(plane.normal);
5432 plane.dist = DotProduct(vert[0], plane.normal);
5433 PlaneClassify(&plane);
5434 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5436 // skip backfaces (except if nocullface is set)
5437 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5439 VectorNegate(plane.normal, plane.normal);
5441 PlaneClassify(&plane);
5445 // find a matching plane if there is one
5446 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5447 if(p->camera_entity == t->camera_entity)
5448 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5450 if (planeindex >= r_waterstate.maxwaterplanes)
5451 return; // nothing we can do, out of planes
5453 // if this triangle does not fit any known plane rendered this frame, add one
5454 if (planeindex >= r_waterstate.numwaterplanes)
5456 // store the new plane
5457 r_waterstate.numwaterplanes++;
5459 // clear materialflags and pvs
5460 p->materialflags = 0;
5461 p->pvsvalid = false;
5462 p->camera_entity = t->camera_entity;
5463 VectorCopy(surface->mins, p->mins);
5464 VectorCopy(surface->maxs, p->maxs);
5469 p->mins[0] = min(p->mins[0], surface->mins[0]);
5470 p->mins[1] = min(p->mins[1], surface->mins[1]);
5471 p->mins[2] = min(p->mins[2], surface->mins[2]);
5472 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5473 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5474 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5476 // merge this surface's materialflags into the waterplane
5477 p->materialflags |= t->currentmaterialflags;
5478 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5480 // merge this surface's PVS into the waterplane
5481 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5482 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5483 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5485 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5491 static void R_Water_ProcessPlanes(void)
5494 r_refdef_view_t originalview;
5495 r_refdef_view_t myview;
5497 r_waterstate_waterplane_t *p;
5500 originalview = r_refdef.view;
5502 // make sure enough textures are allocated
5503 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5505 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5507 if (!p->texture_refraction)
5508 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);
5509 if (!p->texture_refraction)
5512 else if (p->materialflags & MATERIALFLAG_CAMERA)
5514 if (!p->texture_camera)
5515 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);
5516 if (!p->texture_camera)
5520 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5522 if (!p->texture_reflection)
5523 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);
5524 if (!p->texture_reflection)
5530 r_refdef.view = originalview;
5531 r_refdef.view.showdebug = false;
5532 r_refdef.view.width = r_waterstate.waterwidth;
5533 r_refdef.view.height = r_waterstate.waterheight;
5534 r_refdef.view.useclipplane = true;
5535 myview = r_refdef.view;
5536 r_waterstate.renderingscene = true;
5537 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5539 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5541 r_refdef.view = myview;
5542 if(r_water_scissormode.integer)
5545 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5546 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5549 // render reflected scene and copy into texture
5550 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5551 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5552 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5553 r_refdef.view.clipplane = p->plane;
5555 // reverse the cullface settings for this render
5556 r_refdef.view.cullface_front = GL_FRONT;
5557 r_refdef.view.cullface_back = GL_BACK;
5558 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5560 r_refdef.view.usecustompvs = true;
5562 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5564 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5567 R_ResetViewRendering3D();
5568 R_ClearScreen(r_refdef.fogenabled);
5569 if(r_water_scissormode.integer & 2)
5570 R_View_UpdateWithScissor(myscissor);
5573 if(r_water_scissormode.integer & 1)
5574 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5577 R_Mesh_CopyToTexture(p->texture_reflection, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5580 // render the normal view scene and copy into texture
5581 // (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)
5582 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5584 r_refdef.view = myview;
5585 if(r_water_scissormode.integer)
5588 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5589 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5592 r_waterstate.renderingrefraction = true;
5594 r_refdef.view.clipplane = p->plane;
5595 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5596 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5598 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5600 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5601 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5602 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5603 R_RenderView_UpdateViewVectors();
5604 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5606 r_refdef.view.usecustompvs = true;
5607 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);
5611 PlaneClassify(&r_refdef.view.clipplane);
5613 R_ResetViewRendering3D();
5614 R_ClearScreen(r_refdef.fogenabled);
5615 if(r_water_scissormode.integer & 2)
5616 R_View_UpdateWithScissor(myscissor);
5619 if(r_water_scissormode.integer & 1)
5620 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5623 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);
5624 r_waterstate.renderingrefraction = false;
5626 else if (p->materialflags & MATERIALFLAG_CAMERA)
5628 r_refdef.view = myview;
5630 r_refdef.view.clipplane = p->plane;
5631 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5632 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5634 r_refdef.view.width = r_waterstate.camerawidth;
5635 r_refdef.view.height = r_waterstate.cameraheight;
5636 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5637 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5639 if(p->camera_entity)
5641 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5642 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5645 // note: all of the view is used for displaying... so
5646 // there is no use in scissoring
5648 // reverse the cullface settings for this render
5649 r_refdef.view.cullface_front = GL_FRONT;
5650 r_refdef.view.cullface_back = GL_BACK;
5651 // also reverse the view matrix
5652 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
5653 R_RenderView_UpdateViewVectors();
5654 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5656 r_refdef.view.usecustompvs = true;
5657 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);
5660 // camera needs no clipplane
5661 r_refdef.view.useclipplane = false;
5663 PlaneClassify(&r_refdef.view.clipplane);
5665 R_ResetViewRendering3D();
5666 R_ClearScreen(r_refdef.fogenabled);
5670 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);
5671 r_waterstate.renderingrefraction = false;
5675 r_waterstate.renderingscene = false;
5676 r_refdef.view = originalview;
5677 R_ResetViewRendering3D();
5678 R_ClearScreen(r_refdef.fogenabled);
5682 r_refdef.view = originalview;
5683 r_waterstate.renderingscene = false;
5684 Cvar_SetValueQuick(&r_water, 0);
5685 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5689 void R_Bloom_StartFrame(void)
5691 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5692 int viewwidth, viewheight;
5695 if (r_viewscale_fpsscaling.integer)
5697 double actualframetime;
5698 double targetframetime;
5700 actualframetime = r_refdef.lastdrawscreentime;
5701 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5702 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5703 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5704 if (r_viewscale_fpsscaling_stepsize.value > 0)
5705 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5706 viewscalefpsadjusted += adjust;
5707 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5710 viewscalefpsadjusted = 1.0f;
5712 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5714 switch(vid.renderpath)
5716 case RENDERPATH_GL20:
5717 case RENDERPATH_D3D9:
5718 case RENDERPATH_D3D10:
5719 case RENDERPATH_D3D11:
5720 case RENDERPATH_SOFT:
5721 case RENDERPATH_GLES2:
5723 case RENDERPATH_GL13:
5724 case RENDERPATH_GL11:
5728 // set bloomwidth and bloomheight to the bloom resolution that will be
5729 // used (often less than the screen resolution for faster rendering)
5730 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5731 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5732 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5733 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5734 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5736 // calculate desired texture sizes
5737 if (vid.support.arb_texture_non_power_of_two)
5739 screentexturewidth = vid.width;
5740 screentextureheight = vid.height;
5741 bloomtexturewidth = r_bloomstate.bloomwidth;
5742 bloomtextureheight = r_bloomstate.bloomheight;
5746 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
5747 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
5748 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
5749 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
5752 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))
5754 Cvar_SetValueQuick(&r_hdr, 0);
5755 Cvar_SetValueQuick(&r_bloom, 0);
5756 Cvar_SetValueQuick(&r_motionblur, 0);
5757 Cvar_SetValueQuick(&r_damageblur, 0);
5760 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)
5761 screentexturewidth = screentextureheight = 0;
5762 if (!r_hdr.integer && !r_bloom.integer)
5763 bloomtexturewidth = bloomtextureheight = 0;
5765 textype = TEXTYPE_COLORBUFFER;
5766 switch (vid.renderpath)
5768 case RENDERPATH_GL20:
5769 case RENDERPATH_GLES2:
5770 if (vid.support.ext_framebuffer_object)
5772 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5773 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5776 case RENDERPATH_D3D9:
5777 case RENDERPATH_D3D10:
5778 case RENDERPATH_D3D11:
5779 case RENDERPATH_SOFT:
5780 case RENDERPATH_GL13:
5781 case RENDERPATH_GL11:
5785 // allocate textures as needed
5786 if (r_bloomstate.screentexturewidth != screentexturewidth
5787 || r_bloomstate.screentextureheight != screentextureheight
5788 || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5789 || r_bloomstate.bloomtextureheight != bloomtextureheight
5790 || r_bloomstate.texturetype != textype
5791 || r_bloomstate.viewfbo != r_viewfbo.integer)
5793 if (r_bloomstate.texture_bloom)
5794 R_FreeTexture(r_bloomstate.texture_bloom);
5795 r_bloomstate.texture_bloom = NULL;
5796 if (r_bloomstate.texture_screen)
5797 R_FreeTexture(r_bloomstate.texture_screen);
5798 r_bloomstate.texture_screen = NULL;
5799 if (r_bloomstate.fbo_framebuffer)
5800 R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5801 r_bloomstate.fbo_framebuffer = 0;
5802 if (r_bloomstate.texture_framebuffercolor)
5803 R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5804 r_bloomstate.texture_framebuffercolor = NULL;
5805 if (r_bloomstate.texture_framebufferdepth)
5806 R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5807 r_bloomstate.texture_framebufferdepth = NULL;
5808 r_bloomstate.screentexturewidth = screentexturewidth;
5809 r_bloomstate.screentextureheight = screentextureheight;
5810 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5811 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);
5812 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5814 // FIXME: choose depth bits based on a cvar
5815 r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5816 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);
5817 r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5818 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5819 // render depth into one texture and normalmap into the other
5823 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5824 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5825 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
5826 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
5827 Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
5830 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5831 r_bloomstate.bloomtextureheight = bloomtextureheight;
5832 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5833 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);
5834 r_bloomstate.viewfbo = r_viewfbo.integer;
5835 r_bloomstate.texturetype = textype;
5838 // when doing a reduced render (HDR) we want to use a smaller area
5839 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5840 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5841 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5842 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5843 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5845 // set up a texcoord array for the full resolution screen image
5846 // (we have to keep this around to copy back during final render)
5847 r_bloomstate.screentexcoord2f[0] = 0;
5848 r_bloomstate.screentexcoord2f[1] = (float)viewheight / (float)r_bloomstate.screentextureheight;
5849 r_bloomstate.screentexcoord2f[2] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
5850 r_bloomstate.screentexcoord2f[3] = (float)viewheight / (float)r_bloomstate.screentextureheight;
5851 r_bloomstate.screentexcoord2f[4] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
5852 r_bloomstate.screentexcoord2f[5] = 0;
5853 r_bloomstate.screentexcoord2f[6] = 0;
5854 r_bloomstate.screentexcoord2f[7] = 0;
5856 // set up a texcoord array for the reduced resolution bloom image
5857 // (which will be additive blended over the screen image)
5858 r_bloomstate.bloomtexcoord2f[0] = 0;
5859 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5860 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5861 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5862 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5863 r_bloomstate.bloomtexcoord2f[5] = 0;
5864 r_bloomstate.bloomtexcoord2f[6] = 0;
5865 r_bloomstate.bloomtexcoord2f[7] = 0;
5867 switch(vid.renderpath)
5869 case RENDERPATH_GL11:
5870 case RENDERPATH_GL13:
5871 case RENDERPATH_GL20:
5872 case RENDERPATH_SOFT:
5873 case RENDERPATH_GLES2:
5875 case RENDERPATH_D3D9:
5876 case RENDERPATH_D3D10:
5877 case RENDERPATH_D3D11:
5880 for (i = 0;i < 4;i++)
5882 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5883 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5884 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5885 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5891 if (r_hdr.integer || r_bloom.integer)
5893 r_bloomstate.enabled = true;
5894 r_bloomstate.hdr = r_hdr.integer != 0;
5897 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);
5899 if (r_bloomstate.fbo_framebuffer)
5900 r_refdef.view.clear = true;
5903 void R_Bloom_CopyBloomTexture(float colorscale)
5905 r_refdef.stats.bloom++;
5907 // scale down screen texture to the bloom texture size
5909 R_Mesh_SetMainRenderTargets();
5910 R_SetViewport(&r_bloomstate.viewport);
5911 GL_BlendFunc(GL_ONE, GL_ZERO);
5912 GL_Color(colorscale, colorscale, colorscale, 1);
5913 // 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...
5914 switch(vid.renderpath)
5916 case RENDERPATH_GL11:
5917 case RENDERPATH_GL13:
5918 case RENDERPATH_GL20:
5919 case RENDERPATH_SOFT:
5920 case RENDERPATH_GLES2:
5921 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5923 case RENDERPATH_D3D9:
5924 case RENDERPATH_D3D10:
5925 case RENDERPATH_D3D11:
5926 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5929 // TODO: do boxfilter scale-down in shader?
5930 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5931 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5932 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5934 // we now have a bloom image in the framebuffer
5935 // copy it into the bloom image texture for later processing
5936 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);
5937 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5940 void R_Bloom_CopyHDRTexture(void)
5942 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);
5943 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5946 void R_Bloom_MakeTexture(void)
5949 float xoffset, yoffset, r, brighten;
5951 r_refdef.stats.bloom++;
5953 R_ResetViewRendering2D();
5955 // we have a bloom image in the framebuffer
5957 R_SetViewport(&r_bloomstate.viewport);
5959 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5962 r = bound(0, r_bloom_colorexponent.value / x, 1);
5963 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5965 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5966 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5967 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5968 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5970 // copy the vertically blurred bloom view to a texture
5971 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);
5972 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5975 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5976 brighten = r_bloom_brighten.value;
5978 brighten *= r_hdr_range.value;
5979 brighten = sqrt(brighten);
5981 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5982 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5984 for (dir = 0;dir < 2;dir++)
5986 // blend on at multiple vertical offsets to achieve a vertical blur
5987 // TODO: do offset blends using GLSL
5988 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5989 GL_BlendFunc(GL_ONE, GL_ZERO);
5990 for (x = -range;x <= range;x++)
5992 if (!dir){xoffset = 0;yoffset = x;}
5993 else {xoffset = x;yoffset = 0;}
5994 xoffset /= (float)r_bloomstate.bloomtexturewidth;
5995 yoffset /= (float)r_bloomstate.bloomtextureheight;
5996 // compute a texcoord array with the specified x and y offset
5997 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
5998 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5999 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6000 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6001 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6002 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6003 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6004 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6005 // this r value looks like a 'dot' particle, fading sharply to
6006 // black at the edges
6007 // (probably not realistic but looks good enough)
6008 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6009 //r = brighten/(range*2+1);
6010 r = brighten / (range * 2 + 1);
6012 r *= (1 - x*x/(float)(range*range));
6013 GL_Color(r, r, r, 1);
6014 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6015 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6016 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6017 GL_BlendFunc(GL_ONE, GL_ONE);
6020 // copy the vertically blurred bloom view to a texture
6021 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);
6022 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6026 void R_HDR_RenderBloomTexture(void)
6028 int oldwidth, oldheight;
6029 float oldcolorscale;
6030 qboolean oldwaterstate;
6032 oldwaterstate = r_waterstate.enabled;
6033 oldcolorscale = r_refdef.view.colorscale;
6034 oldwidth = r_refdef.view.width;
6035 oldheight = r_refdef.view.height;
6036 r_refdef.view.width = r_bloomstate.bloomwidth;
6037 r_refdef.view.height = r_bloomstate.bloomheight;
6039 if(r_hdr.integer < 2)
6040 r_waterstate.enabled = false;
6042 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
6043 // TODO: add exposure compensation features
6044 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6046 r_refdef.view.showdebug = false;
6047 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6049 R_ResetViewRendering3D();
6051 R_ClearScreen(r_refdef.fogenabled);
6052 if (r_timereport_active)
6053 R_TimeReport("HDRclear");
6056 if (r_timereport_active)
6057 R_TimeReport("visibility");
6059 // only do secondary renders with HDR if r_hdr is 2 or higher
6060 r_waterstate.numwaterplanes = 0;
6061 if (r_waterstate.enabled)
6062 R_RenderWaterPlanes();
6064 r_refdef.view.showdebug = true;
6066 r_waterstate.numwaterplanes = 0;
6068 R_ResetViewRendering2D();
6070 R_Bloom_CopyHDRTexture();
6071 R_Bloom_MakeTexture();
6073 // restore the view settings
6074 r_waterstate.enabled = oldwaterstate;
6075 r_refdef.view.width = oldwidth;
6076 r_refdef.view.height = oldheight;
6077 r_refdef.view.colorscale = oldcolorscale;
6079 R_ResetViewRendering3D();
6081 R_ClearScreen(r_refdef.fogenabled);
6082 if (r_timereport_active)
6083 R_TimeReport("viewclear");
6086 static void R_BlendView(void)
6088 unsigned int permutation;
6089 float uservecs[4][4];
6091 switch (vid.renderpath)
6093 case RENDERPATH_GL20:
6094 case RENDERPATH_D3D9:
6095 case RENDERPATH_D3D10:
6096 case RENDERPATH_D3D11:
6097 case RENDERPATH_SOFT:
6098 case RENDERPATH_GLES2:
6100 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6101 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6102 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6103 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6104 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6106 if (r_bloomstate.texture_screen)
6108 // make sure the buffer is available
6109 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6111 R_ResetViewRendering2D();
6112 R_Mesh_SetMainRenderTargets();
6114 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6116 // declare variables
6118 static float avgspeed;
6120 speed = VectorLength(cl.movement_velocity);
6122 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6123 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6125 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6126 speed = bound(0, speed, 1);
6127 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6129 // calculate values into a standard alpha
6130 cl.motionbluralpha = 1 - exp(-
6132 (r_motionblur.value * speed / 80)
6134 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6137 max(0.0001, cl.time - cl.oldtime) // fps independent
6140 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6141 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6143 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6145 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6146 GL_Color(1, 1, 1, cl.motionbluralpha);
6147 switch(vid.renderpath)
6149 case RENDERPATH_GL11:
6150 case RENDERPATH_GL13:
6151 case RENDERPATH_GL20:
6152 case RENDERPATH_SOFT:
6153 case RENDERPATH_GLES2:
6154 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6156 case RENDERPATH_D3D9:
6157 case RENDERPATH_D3D10:
6158 case RENDERPATH_D3D11:
6159 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6162 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6163 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6164 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6168 // copy view into the screen texture
6169 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);
6170 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6172 else if (!r_bloomstate.texture_bloom)
6174 // we may still have to do view tint...
6175 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6177 // apply a color tint to the whole view
6178 R_ResetViewRendering2D();
6179 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6180 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6181 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6182 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6183 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6185 break; // no screen processing, no bloom, skip it
6188 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6190 // render simple bloom effect
6191 // copy the screen and shrink it and darken it for the bloom process
6192 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6193 // make the bloom texture
6194 R_Bloom_MakeTexture();
6197 #if _MSC_VER >= 1400
6198 #define sscanf sscanf_s
6200 memset(uservecs, 0, sizeof(uservecs));
6201 if (r_glsl_postprocess_uservec1_enable.integer)
6202 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6203 if (r_glsl_postprocess_uservec2_enable.integer)
6204 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6205 if (r_glsl_postprocess_uservec3_enable.integer)
6206 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6207 if (r_glsl_postprocess_uservec4_enable.integer)
6208 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6210 R_ResetViewRendering2D();
6211 GL_Color(1, 1, 1, 1);
6212 GL_BlendFunc(GL_ONE, GL_ZERO);
6214 switch(vid.renderpath)
6216 case RENDERPATH_GL20:
6217 case RENDERPATH_GLES2:
6218 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6219 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6220 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6221 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6222 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6223 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]);
6224 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6225 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]);
6226 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]);
6227 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]);
6228 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]);
6229 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6230 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6231 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);
6233 case RENDERPATH_D3D9:
6235 // 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...
6236 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6237 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6238 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6239 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6240 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6241 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6242 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6243 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6244 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6245 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6246 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6247 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6248 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6249 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6252 case RENDERPATH_D3D10:
6253 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6255 case RENDERPATH_D3D11:
6256 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6258 case RENDERPATH_SOFT:
6259 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6260 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6261 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6262 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6263 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6264 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6265 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6266 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6267 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6268 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6269 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6270 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6271 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6272 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6277 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6278 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6280 case RENDERPATH_GL13:
6281 case RENDERPATH_GL11:
6282 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6284 // apply a color tint to the whole view
6285 R_ResetViewRendering2D();
6286 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6287 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6288 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6289 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6290 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6296 matrix4x4_t r_waterscrollmatrix;
6298 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6300 if (r_refdef.fog_density)
6302 r_refdef.fogcolor[0] = r_refdef.fog_red;
6303 r_refdef.fogcolor[1] = r_refdef.fog_green;
6304 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6306 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6307 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6308 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6309 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6313 VectorCopy(r_refdef.fogcolor, fogvec);
6314 // color.rgb *= ContrastBoost * SceneBrightness;
6315 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6316 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6317 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6318 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6323 void R_UpdateVariables(void)
6327 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6329 r_refdef.farclip = r_farclip_base.value;
6330 if (r_refdef.scene.worldmodel)
6331 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6332 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6334 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6335 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6336 r_refdef.polygonfactor = 0;
6337 r_refdef.polygonoffset = 0;
6338 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6339 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6341 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6342 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6343 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6344 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6345 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6346 if (FAKELIGHT_ENABLED)
6348 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6350 if (r_showsurfaces.integer)
6352 r_refdef.scene.rtworld = false;
6353 r_refdef.scene.rtworldshadows = false;
6354 r_refdef.scene.rtdlight = false;
6355 r_refdef.scene.rtdlightshadows = false;
6356 r_refdef.lightmapintensity = 0;
6359 if (gamemode == GAME_NEHAHRA)
6361 if (gl_fogenable.integer)
6363 r_refdef.oldgl_fogenable = true;
6364 r_refdef.fog_density = gl_fogdensity.value;
6365 r_refdef.fog_red = gl_fogred.value;
6366 r_refdef.fog_green = gl_foggreen.value;
6367 r_refdef.fog_blue = gl_fogblue.value;
6368 r_refdef.fog_alpha = 1;
6369 r_refdef.fog_start = 0;
6370 r_refdef.fog_end = gl_skyclip.value;
6371 r_refdef.fog_height = 1<<30;
6372 r_refdef.fog_fadedepth = 128;
6374 else if (r_refdef.oldgl_fogenable)
6376 r_refdef.oldgl_fogenable = false;
6377 r_refdef.fog_density = 0;
6378 r_refdef.fog_red = 0;
6379 r_refdef.fog_green = 0;
6380 r_refdef.fog_blue = 0;
6381 r_refdef.fog_alpha = 0;
6382 r_refdef.fog_start = 0;
6383 r_refdef.fog_end = 0;
6384 r_refdef.fog_height = 1<<30;
6385 r_refdef.fog_fadedepth = 128;
6389 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6390 r_refdef.fog_start = max(0, r_refdef.fog_start);
6391 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6393 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6395 if (r_refdef.fog_density && r_drawfog.integer)
6397 r_refdef.fogenabled = true;
6398 // this is the point where the fog reaches 0.9986 alpha, which we
6399 // consider a good enough cutoff point for the texture
6400 // (0.9986 * 256 == 255.6)
6401 if (r_fog_exp2.integer)
6402 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6404 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6405 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6406 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6407 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6408 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6409 R_BuildFogHeightTexture();
6410 // fog color was already set
6411 // update the fog texture
6412 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)
6413 R_BuildFogTexture();
6414 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6415 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6418 r_refdef.fogenabled = false;
6420 switch(vid.renderpath)
6422 case RENDERPATH_GL20:
6423 case RENDERPATH_D3D9:
6424 case RENDERPATH_D3D10:
6425 case RENDERPATH_D3D11:
6426 case RENDERPATH_SOFT:
6427 case RENDERPATH_GLES2:
6428 if(v_glslgamma.integer && !vid_gammatables_trivial)
6430 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6432 // build GLSL gamma texture
6433 #define RAMPWIDTH 256
6434 unsigned short ramp[RAMPWIDTH * 3];
6435 unsigned char rampbgr[RAMPWIDTH][4];
6438 r_texture_gammaramps_serial = vid_gammatables_serial;
6440 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6441 for(i = 0; i < RAMPWIDTH; ++i)
6443 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6444 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6445 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6448 if (r_texture_gammaramps)
6450 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6454 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6460 // remove GLSL gamma texture
6463 case RENDERPATH_GL13:
6464 case RENDERPATH_GL11:
6469 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6470 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6476 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6477 if( scenetype != r_currentscenetype ) {
6478 // store the old scenetype
6479 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6480 r_currentscenetype = scenetype;
6481 // move in the new scene
6482 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6491 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6493 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6494 if( scenetype == r_currentscenetype ) {
6495 return &r_refdef.scene;
6497 return &r_scenes_store[ scenetype ];
6506 int dpsoftrast_test;
6507 void R_RenderView(void)
6509 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6511 dpsoftrast_test = r_test.integer;
6513 if (r_timereport_active)
6514 R_TimeReport("start");
6515 r_textureframe++; // used only by R_GetCurrentTexture
6516 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6518 if(R_CompileShader_CheckStaticParms())
6521 if (!r_drawentities.integer)
6522 r_refdef.scene.numentities = 0;
6524 R_AnimCache_ClearCache();
6525 R_FrameData_NewFrame();
6527 /* adjust for stereo display */
6528 if(R_Stereo_Active())
6530 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);
6531 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6534 if (r_refdef.view.isoverlay)
6536 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6537 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6538 R_TimeReport("depthclear");
6540 r_refdef.view.showdebug = false;
6542 r_waterstate.enabled = false;
6543 r_waterstate.numwaterplanes = 0;
6547 r_refdef.view.matrix = originalmatrix;
6553 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6555 r_refdef.view.matrix = originalmatrix;
6556 return; //Host_Error ("R_RenderView: NULL worldmodel");
6559 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6561 R_RenderView_UpdateViewVectors();
6563 R_Shadow_UpdateWorldLightSelection();
6565 R_Bloom_StartFrame();
6566 R_Water_StartFrame();
6569 if (r_timereport_active)
6570 R_TimeReport("viewsetup");
6572 R_ResetViewRendering3D();
6574 if (r_refdef.view.clear || r_refdef.fogenabled)
6576 R_ClearScreen(r_refdef.fogenabled);
6577 if (r_timereport_active)
6578 R_TimeReport("viewclear");
6580 r_refdef.view.clear = true;
6582 // this produces a bloom texture to be used in R_BlendView() later
6583 if (r_hdr.integer && r_bloomstate.bloomwidth)
6585 R_HDR_RenderBloomTexture();
6586 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6587 r_textureframe++; // used only by R_GetCurrentTexture
6590 r_refdef.view.showdebug = true;
6593 if (r_timereport_active)
6594 R_TimeReport("visibility");
6596 r_waterstate.numwaterplanes = 0;
6597 if (r_waterstate.enabled)
6598 R_RenderWaterPlanes();
6601 r_waterstate.numwaterplanes = 0;
6604 if (r_timereport_active)
6605 R_TimeReport("blendview");
6607 GL_Scissor(0, 0, vid.width, vid.height);
6608 GL_ScissorTest(false);
6610 r_refdef.view.matrix = originalmatrix;
6615 void R_RenderWaterPlanes(void)
6617 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6619 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6620 if (r_timereport_active)
6621 R_TimeReport("waterworld");
6624 // don't let sound skip if going slow
6625 if (r_refdef.scene.extraupdate)
6628 R_DrawModelsAddWaterPlanes();
6629 if (r_timereport_active)
6630 R_TimeReport("watermodels");
6632 if (r_waterstate.numwaterplanes)
6634 R_Water_ProcessPlanes();
6635 if (r_timereport_active)
6636 R_TimeReport("waterscenes");
6640 extern void R_DrawLightningBeams (void);
6641 extern void VM_CL_AddPolygonsToMeshQueue (void);
6642 extern void R_DrawPortals (void);
6643 extern cvar_t cl_locs_show;
6644 static void R_DrawLocs(void);
6645 static void R_DrawEntityBBoxes(void);
6646 static void R_DrawModelDecals(void);
6647 extern void R_DrawModelShadows(void);
6648 extern void R_DrawModelShadowMaps(void);
6649 extern cvar_t cl_decals_newsystem;
6650 extern qboolean r_shadow_usingdeferredprepass;
6651 void R_RenderScene(void)
6653 qboolean shadowmapping = false;
6655 if (r_timereport_active)
6656 R_TimeReport("beginscene");
6658 r_refdef.stats.renders++;
6662 // don't let sound skip if going slow
6663 if (r_refdef.scene.extraupdate)
6666 R_MeshQueue_BeginScene();
6670 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);
6672 if (r_timereport_active)
6673 R_TimeReport("skystartframe");
6675 if (cl.csqc_vidvars.drawworld)
6677 // don't let sound skip if going slow
6678 if (r_refdef.scene.extraupdate)
6681 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6683 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6684 if (r_timereport_active)
6685 R_TimeReport("worldsky");
6688 if (R_DrawBrushModelsSky() && r_timereport_active)
6689 R_TimeReport("bmodelsky");
6691 if (skyrendermasked && skyrenderlater)
6693 // we have to force off the water clipping plane while rendering sky
6697 if (r_timereport_active)
6698 R_TimeReport("sky");
6702 R_AnimCache_CacheVisibleEntities();
6703 if (r_timereport_active)
6704 R_TimeReport("animation");
6706 R_Shadow_PrepareLights();
6707 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6708 R_Shadow_PrepareModelShadows();
6709 if (r_timereport_active)
6710 R_TimeReport("preparelights");
6712 if (R_Shadow_ShadowMappingEnabled())
6713 shadowmapping = true;
6715 if (r_shadow_usingdeferredprepass)
6716 R_Shadow_DrawPrepass();
6718 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6720 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6721 if (r_timereport_active)
6722 R_TimeReport("worlddepth");
6724 if (r_depthfirst.integer >= 2)
6726 R_DrawModelsDepth();
6727 if (r_timereport_active)
6728 R_TimeReport("modeldepth");
6731 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6733 R_DrawModelShadowMaps();
6734 R_ResetViewRendering3D();
6735 // don't let sound skip if going slow
6736 if (r_refdef.scene.extraupdate)
6740 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6742 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6743 if (r_timereport_active)
6744 R_TimeReport("world");
6747 // don't let sound skip if going slow
6748 if (r_refdef.scene.extraupdate)
6752 if (r_timereport_active)
6753 R_TimeReport("models");
6755 // don't let sound skip if going slow
6756 if (r_refdef.scene.extraupdate)
6759 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6761 R_DrawModelShadows();
6762 R_ResetViewRendering3D();
6763 // don't let sound skip if going slow
6764 if (r_refdef.scene.extraupdate)
6768 if (!r_shadow_usingdeferredprepass)
6770 R_Shadow_DrawLights();
6771 if (r_timereport_active)
6772 R_TimeReport("rtlights");
6775 // don't let sound skip if going slow
6776 if (r_refdef.scene.extraupdate)
6779 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6781 R_DrawModelShadows();
6782 R_ResetViewRendering3D();
6783 // don't let sound skip if going slow
6784 if (r_refdef.scene.extraupdate)
6788 if (cl.csqc_vidvars.drawworld)
6790 if (cl_decals_newsystem.integer)
6792 R_DrawModelDecals();
6793 if (r_timereport_active)
6794 R_TimeReport("modeldecals");
6799 if (r_timereport_active)
6800 R_TimeReport("decals");
6804 if (r_timereport_active)
6805 R_TimeReport("particles");
6808 if (r_timereport_active)
6809 R_TimeReport("explosions");
6811 R_DrawLightningBeams();
6812 if (r_timereport_active)
6813 R_TimeReport("lightning");
6816 VM_CL_AddPolygonsToMeshQueue();
6818 if (r_refdef.view.showdebug)
6820 if (cl_locs_show.integer)
6823 if (r_timereport_active)
6824 R_TimeReport("showlocs");
6827 if (r_drawportals.integer)
6830 if (r_timereport_active)
6831 R_TimeReport("portals");
6834 if (r_showbboxes.value > 0)
6836 R_DrawEntityBBoxes();
6837 if (r_timereport_active)
6838 R_TimeReport("bboxes");
6842 R_MeshQueue_RenderTransparent();
6843 if (r_timereport_active)
6844 R_TimeReport("drawtrans");
6846 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))
6848 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6849 if (r_timereport_active)
6850 R_TimeReport("worlddebug");
6851 R_DrawModelsDebug();
6852 if (r_timereport_active)
6853 R_TimeReport("modeldebug");
6856 if (cl.csqc_vidvars.drawworld)
6858 R_Shadow_DrawCoronas();
6859 if (r_timereport_active)
6860 R_TimeReport("coronas");
6865 GL_DepthTest(false);
6866 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6867 GL_Color(1, 1, 1, 1);
6868 qglBegin(GL_POLYGON);
6869 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6870 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6871 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6872 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6874 qglBegin(GL_POLYGON);
6875 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]);
6876 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]);
6877 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]);
6878 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]);
6880 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6884 // don't let sound skip if going slow
6885 if (r_refdef.scene.extraupdate)
6888 R_ResetViewRendering2D();
6891 static const unsigned short bboxelements[36] =
6901 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6904 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6906 RSurf_ActiveWorldEntity();
6908 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6909 GL_DepthMask(false);
6910 GL_DepthRange(0, 1);
6911 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6912 // R_Mesh_ResetTextureState();
6914 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6915 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6916 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6917 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6918 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6919 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6920 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6921 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6922 R_FillColors(color4f, 8, cr, cg, cb, ca);
6923 if (r_refdef.fogenabled)
6925 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6927 f1 = RSurf_FogVertex(v);
6929 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6930 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6931 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6934 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6935 R_Mesh_ResetTextureState();
6936 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6937 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6940 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6944 prvm_edict_t *edict;
6945 prvm_prog_t *prog_save = prog;
6947 // this function draws bounding boxes of server entities
6951 GL_CullFace(GL_NONE);
6952 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6956 for (i = 0;i < numsurfaces;i++)
6958 edict = PRVM_EDICT_NUM(surfacelist[i]);
6959 switch ((int)edict->fields.server->solid)
6961 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
6962 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
6963 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
6964 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6965 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
6966 default: Vector4Set(color, 0, 0, 0, 0.50);break;
6968 color[3] *= r_showbboxes.value;
6969 color[3] = bound(0, color[3], 1);
6970 GL_DepthTest(!r_showdisabledepthtest.integer);
6971 GL_CullFace(r_refdef.view.cullface_front);
6972 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6978 static void R_DrawEntityBBoxes(void)
6981 prvm_edict_t *edict;
6983 prvm_prog_t *prog_save = prog;
6985 // this function draws bounding boxes of server entities
6991 for (i = 0;i < prog->num_edicts;i++)
6993 edict = PRVM_EDICT_NUM(i);
6994 if (edict->priv.server->free)
6996 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6997 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
6999 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
7001 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7002 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7008 static const int nomodelelement3i[24] =
7020 static const unsigned short nomodelelement3s[24] =
7032 static const float nomodelvertex3f[6*3] =
7042 static const float nomodelcolor4f[6*4] =
7044 0.0f, 0.0f, 0.5f, 1.0f,
7045 0.0f, 0.0f, 0.5f, 1.0f,
7046 0.0f, 0.5f, 0.0f, 1.0f,
7047 0.0f, 0.5f, 0.0f, 1.0f,
7048 0.5f, 0.0f, 0.0f, 1.0f,
7049 0.5f, 0.0f, 0.0f, 1.0f
7052 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7058 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);
7060 // this is only called once per entity so numsurfaces is always 1, and
7061 // surfacelist is always {0}, so this code does not handle batches
7063 if (rsurface.ent_flags & RENDER_ADDITIVE)
7065 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7066 GL_DepthMask(false);
7068 else if (rsurface.colormod[3] < 1)
7070 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7071 GL_DepthMask(false);
7075 GL_BlendFunc(GL_ONE, GL_ZERO);
7078 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7079 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7080 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7081 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7082 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7083 for (i = 0, c = color4f;i < 6;i++, c += 4)
7085 c[0] *= rsurface.colormod[0];
7086 c[1] *= rsurface.colormod[1];
7087 c[2] *= rsurface.colormod[2];
7088 c[3] *= rsurface.colormod[3];
7090 if (r_refdef.fogenabled)
7092 for (i = 0, c = color4f;i < 6;i++, c += 4)
7094 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7096 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7097 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7098 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7101 // R_Mesh_ResetTextureState();
7102 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7103 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7104 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7107 void R_DrawNoModel(entity_render_t *ent)
7110 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7111 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7112 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7114 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7117 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7119 vec3_t right1, right2, diff, normal;
7121 VectorSubtract (org2, org1, normal);
7123 // calculate 'right' vector for start
7124 VectorSubtract (r_refdef.view.origin, org1, diff);
7125 CrossProduct (normal, diff, right1);
7126 VectorNormalize (right1);
7128 // calculate 'right' vector for end
7129 VectorSubtract (r_refdef.view.origin, org2, diff);
7130 CrossProduct (normal, diff, right2);
7131 VectorNormalize (right2);
7133 vert[ 0] = org1[0] + width * right1[0];
7134 vert[ 1] = org1[1] + width * right1[1];
7135 vert[ 2] = org1[2] + width * right1[2];
7136 vert[ 3] = org1[0] - width * right1[0];
7137 vert[ 4] = org1[1] - width * right1[1];
7138 vert[ 5] = org1[2] - width * right1[2];
7139 vert[ 6] = org2[0] - width * right2[0];
7140 vert[ 7] = org2[1] - width * right2[1];
7141 vert[ 8] = org2[2] - width * right2[2];
7142 vert[ 9] = org2[0] + width * right2[0];
7143 vert[10] = org2[1] + width * right2[1];
7144 vert[11] = org2[2] + width * right2[2];
7147 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)
7149 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7150 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7151 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7152 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7153 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7154 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7155 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7156 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7157 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7158 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7159 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7160 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7163 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7168 VectorSet(v, x, y, z);
7169 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7170 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7172 if (i == mesh->numvertices)
7174 if (mesh->numvertices < mesh->maxvertices)
7176 VectorCopy(v, vertex3f);
7177 mesh->numvertices++;
7179 return mesh->numvertices;
7185 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7189 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7190 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7191 e = mesh->element3i + mesh->numtriangles * 3;
7192 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7194 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7195 if (mesh->numtriangles < mesh->maxtriangles)
7200 mesh->numtriangles++;
7202 element[1] = element[2];
7206 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7210 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7211 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7212 e = mesh->element3i + mesh->numtriangles * 3;
7213 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7215 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7216 if (mesh->numtriangles < mesh->maxtriangles)
7221 mesh->numtriangles++;
7223 element[1] = element[2];
7227 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7228 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7230 int planenum, planenum2;
7233 mplane_t *plane, *plane2;
7235 double temppoints[2][256*3];
7236 // figure out how large a bounding box we need to properly compute this brush
7238 for (w = 0;w < numplanes;w++)
7239 maxdist = max(maxdist, fabs(planes[w].dist));
7240 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7241 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7242 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7246 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7247 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7249 if (planenum2 == planenum)
7251 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);
7254 if (tempnumpoints < 3)
7256 // generate elements forming a triangle fan for this polygon
7257 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7261 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)
7263 texturelayer_t *layer;
7264 layer = t->currentlayers + t->currentnumlayers++;
7266 layer->depthmask = depthmask;
7267 layer->blendfunc1 = blendfunc1;
7268 layer->blendfunc2 = blendfunc2;
7269 layer->texture = texture;
7270 layer->texmatrix = *matrix;
7271 layer->color[0] = r;
7272 layer->color[1] = g;
7273 layer->color[2] = b;
7274 layer->color[3] = a;
7277 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7279 if(parms[0] == 0 && parms[1] == 0)
7281 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7282 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7287 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7290 index = parms[2] + r_refdef.scene.time * parms[3];
7291 index -= floor(index);
7292 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7295 case Q3WAVEFUNC_NONE:
7296 case Q3WAVEFUNC_NOISE:
7297 case Q3WAVEFUNC_COUNT:
7300 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7301 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7302 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7303 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7304 case Q3WAVEFUNC_TRIANGLE:
7306 f = index - floor(index);
7317 f = parms[0] + parms[1] * f;
7318 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7319 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7323 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7328 matrix4x4_t matrix, temp;
7329 switch(tcmod->tcmod)
7333 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7334 matrix = r_waterscrollmatrix;
7336 matrix = identitymatrix;
7338 case Q3TCMOD_ENTITYTRANSLATE:
7339 // this is used in Q3 to allow the gamecode to control texcoord
7340 // scrolling on the entity, which is not supported in darkplaces yet.
7341 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7343 case Q3TCMOD_ROTATE:
7344 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7345 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7346 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7349 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7351 case Q3TCMOD_SCROLL:
7352 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7354 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7355 w = (int) tcmod->parms[0];
7356 h = (int) tcmod->parms[1];
7357 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7359 idx = (int) floor(f * w * h);
7360 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7362 case Q3TCMOD_STRETCH:
7363 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7364 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7366 case Q3TCMOD_TRANSFORM:
7367 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7368 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7369 VectorSet(tcmat + 6, 0 , 0 , 1);
7370 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7371 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7373 case Q3TCMOD_TURBULENT:
7374 // this is handled in the RSurf_PrepareVertices function
7375 matrix = identitymatrix;
7379 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7382 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7384 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7385 char name[MAX_QPATH];
7386 skinframe_t *skinframe;
7387 unsigned char pixels[296*194];
7388 strlcpy(cache->name, skinname, sizeof(cache->name));
7389 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7390 if (developer_loading.integer)
7391 Con_Printf("loading %s\n", name);
7392 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7393 if (!skinframe || !skinframe->base)
7396 fs_offset_t filesize;
7398 f = FS_LoadFile(name, tempmempool, true, &filesize);
7401 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7402 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7406 cache->skinframe = skinframe;
7409 texture_t *R_GetCurrentTexture(texture_t *t)
7412 const entity_render_t *ent = rsurface.entity;
7413 dp_model_t *model = ent->model;
7414 q3shaderinfo_layer_tcmod_t *tcmod;
7416 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7417 return t->currentframe;
7418 t->update_lastrenderframe = r_textureframe;
7419 t->update_lastrenderentity = (void *)ent;
7421 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7422 t->camera_entity = ent->entitynumber;
7424 t->camera_entity = 0;
7426 // switch to an alternate material if this is a q1bsp animated material
7428 texture_t *texture = t;
7429 int s = rsurface.ent_skinnum;
7430 if ((unsigned int)s >= (unsigned int)model->numskins)
7432 if (model->skinscenes)
7434 if (model->skinscenes[s].framecount > 1)
7435 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7437 s = model->skinscenes[s].firstframe;
7440 t = t + s * model->num_surfaces;
7443 // use an alternate animation if the entity's frame is not 0,
7444 // and only if the texture has an alternate animation
7445 if (rsurface.ent_alttextures && t->anim_total[1])
7446 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7448 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7450 texture->currentframe = t;
7453 // update currentskinframe to be a qw skin or animation frame
7454 if (rsurface.ent_qwskin >= 0)
7456 i = rsurface.ent_qwskin;
7457 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7459 r_qwskincache_size = cl.maxclients;
7461 Mem_Free(r_qwskincache);
7462 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7464 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7465 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7466 t->currentskinframe = r_qwskincache[i].skinframe;
7467 if (t->currentskinframe == NULL)
7468 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7470 else if (t->numskinframes >= 2)
7471 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7472 if (t->backgroundnumskinframes >= 2)
7473 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7475 t->currentmaterialflags = t->basematerialflags;
7476 t->currentalpha = rsurface.colormod[3];
7477 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7478 t->currentalpha *= r_wateralpha.value;
7479 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7480 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7481 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7482 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7483 if (!(rsurface.ent_flags & RENDER_LIGHT))
7484 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7485 else if (FAKELIGHT_ENABLED)
7487 // no modellight if using fakelight for the map
7489 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7491 // pick a model lighting mode
7492 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7493 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7495 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7497 if (rsurface.ent_flags & RENDER_ADDITIVE)
7498 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7499 else if (t->currentalpha < 1)
7500 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7501 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7502 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7503 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7504 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7505 if (t->backgroundnumskinframes)
7506 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7507 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7509 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7510 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7513 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7514 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7515 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7517 // there is no tcmod
7518 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7520 t->currenttexmatrix = r_waterscrollmatrix;
7521 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7523 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7525 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7526 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7529 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7530 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7531 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7532 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7534 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7535 if (t->currentskinframe->qpixels)
7536 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7537 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7538 if (!t->basetexture)
7539 t->basetexture = r_texture_notexture;
7540 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7541 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7542 t->nmaptexture = t->currentskinframe->nmap;
7543 if (!t->nmaptexture)
7544 t->nmaptexture = r_texture_blanknormalmap;
7545 t->glosstexture = r_texture_black;
7546 t->glowtexture = t->currentskinframe->glow;
7547 t->fogtexture = t->currentskinframe->fog;
7548 t->reflectmasktexture = t->currentskinframe->reflect;
7549 if (t->backgroundnumskinframes)
7551 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7552 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7553 t->backgroundglosstexture = r_texture_black;
7554 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7555 if (!t->backgroundnmaptexture)
7556 t->backgroundnmaptexture = r_texture_blanknormalmap;
7560 t->backgroundbasetexture = r_texture_white;
7561 t->backgroundnmaptexture = r_texture_blanknormalmap;
7562 t->backgroundglosstexture = r_texture_black;
7563 t->backgroundglowtexture = NULL;
7565 t->specularpower = r_shadow_glossexponent.value;
7566 // TODO: store reference values for these in the texture?
7567 t->specularscale = 0;
7568 if (r_shadow_gloss.integer > 0)
7570 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7572 if (r_shadow_glossintensity.value > 0)
7574 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7575 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7576 t->specularscale = r_shadow_glossintensity.value;
7579 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7581 t->glosstexture = r_texture_white;
7582 t->backgroundglosstexture = r_texture_white;
7583 t->specularscale = r_shadow_gloss2intensity.value;
7584 t->specularpower = r_shadow_gloss2exponent.value;
7587 t->specularscale *= t->specularscalemod;
7588 t->specularpower *= t->specularpowermod;
7590 // lightmaps mode looks bad with dlights using actual texturing, so turn
7591 // off the colormap and glossmap, but leave the normalmap on as it still
7592 // accurately represents the shading involved
7593 if (gl_lightmaps.integer)
7595 t->basetexture = r_texture_grey128;
7596 t->pantstexture = r_texture_black;
7597 t->shirttexture = r_texture_black;
7598 t->nmaptexture = r_texture_blanknormalmap;
7599 t->glosstexture = r_texture_black;
7600 t->glowtexture = NULL;
7601 t->fogtexture = NULL;
7602 t->reflectmasktexture = NULL;
7603 t->backgroundbasetexture = NULL;
7604 t->backgroundnmaptexture = r_texture_blanknormalmap;
7605 t->backgroundglosstexture = r_texture_black;
7606 t->backgroundglowtexture = NULL;
7607 t->specularscale = 0;
7608 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7611 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7612 VectorClear(t->dlightcolor);
7613 t->currentnumlayers = 0;
7614 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7616 int blendfunc1, blendfunc2;
7618 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7620 blendfunc1 = GL_SRC_ALPHA;
7621 blendfunc2 = GL_ONE;
7623 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7625 blendfunc1 = GL_SRC_ALPHA;
7626 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7628 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7630 blendfunc1 = t->customblendfunc[0];
7631 blendfunc2 = t->customblendfunc[1];
7635 blendfunc1 = GL_ONE;
7636 blendfunc2 = GL_ZERO;
7638 // don't colormod evilblend textures
7639 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7640 VectorSet(t->lightmapcolor, 1, 1, 1);
7641 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7642 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7644 // fullbright is not affected by r_refdef.lightmapintensity
7645 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]);
7646 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7647 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]);
7648 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7649 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]);
7653 vec3_t ambientcolor;
7655 // set the color tint used for lights affecting this surface
7656 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7658 // q3bsp has no lightmap updates, so the lightstylevalue that
7659 // would normally be baked into the lightmap must be
7660 // applied to the color
7661 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7662 if (model->type == mod_brushq3)
7663 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7664 colorscale *= r_refdef.lightmapintensity;
7665 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7666 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7667 // basic lit geometry
7668 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]);
7669 // add pants/shirt if needed
7670 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7671 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]);
7672 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7673 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]);
7674 // now add ambient passes if needed
7675 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7677 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]);
7678 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7679 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]);
7680 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7681 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]);
7684 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7685 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]);
7686 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7688 // if this is opaque use alpha blend which will darken the earlier
7691 // if this is an alpha blended material, all the earlier passes
7692 // were darkened by fog already, so we only need to add the fog
7693 // color ontop through the fog mask texture
7695 // if this is an additive blended material, all the earlier passes
7696 // were darkened by fog already, and we should not add fog color
7697 // (because the background was not darkened, there is no fog color
7698 // that was lost behind it).
7699 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]);
7703 return t->currentframe;
7706 rsurfacestate_t rsurface;
7708 void RSurf_ActiveWorldEntity(void)
7710 dp_model_t *model = r_refdef.scene.worldmodel;
7711 //if (rsurface.entity == r_refdef.scene.worldentity)
7713 rsurface.entity = r_refdef.scene.worldentity;
7714 rsurface.skeleton = NULL;
7715 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7716 rsurface.ent_skinnum = 0;
7717 rsurface.ent_qwskin = -1;
7718 rsurface.ent_shadertime = 0;
7719 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7720 rsurface.matrix = identitymatrix;
7721 rsurface.inversematrix = identitymatrix;
7722 rsurface.matrixscale = 1;
7723 rsurface.inversematrixscale = 1;
7724 R_EntityMatrix(&identitymatrix);
7725 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7726 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7727 rsurface.fograngerecip = r_refdef.fograngerecip;
7728 rsurface.fogheightfade = r_refdef.fogheightfade;
7729 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7730 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7731 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7732 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7733 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7734 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7735 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7736 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7737 rsurface.colormod[3] = 1;
7738 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);
7739 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7740 rsurface.frameblend[0].lerp = 1;
7741 rsurface.ent_alttextures = false;
7742 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7743 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7744 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7745 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7746 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7747 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7748 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7749 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7750 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7751 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7752 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7753 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7754 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7755 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7756 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7757 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7758 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7759 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7760 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7761 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7762 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7763 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7764 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7765 rsurface.modelelement3i = model->surfmesh.data_element3i;
7766 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7767 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7768 rsurface.modelelement3s = model->surfmesh.data_element3s;
7769 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7770 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7771 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7772 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7773 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7774 rsurface.modelsurfaces = model->data_surfaces;
7775 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7776 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7777 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7778 rsurface.modelgeneratedvertex = false;
7779 rsurface.batchgeneratedvertex = false;
7780 rsurface.batchfirstvertex = 0;
7781 rsurface.batchnumvertices = 0;
7782 rsurface.batchfirsttriangle = 0;
7783 rsurface.batchnumtriangles = 0;
7784 rsurface.batchvertex3f = NULL;
7785 rsurface.batchvertex3f_vertexbuffer = NULL;
7786 rsurface.batchvertex3f_bufferoffset = 0;
7787 rsurface.batchsvector3f = NULL;
7788 rsurface.batchsvector3f_vertexbuffer = NULL;
7789 rsurface.batchsvector3f_bufferoffset = 0;
7790 rsurface.batchtvector3f = NULL;
7791 rsurface.batchtvector3f_vertexbuffer = NULL;
7792 rsurface.batchtvector3f_bufferoffset = 0;
7793 rsurface.batchnormal3f = NULL;
7794 rsurface.batchnormal3f_vertexbuffer = NULL;
7795 rsurface.batchnormal3f_bufferoffset = 0;
7796 rsurface.batchlightmapcolor4f = NULL;
7797 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7798 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7799 rsurface.batchtexcoordtexture2f = NULL;
7800 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7801 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7802 rsurface.batchtexcoordlightmap2f = NULL;
7803 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7804 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7805 rsurface.batchvertexmesh = NULL;
7806 rsurface.batchvertexmeshbuffer = NULL;
7807 rsurface.batchvertex3fbuffer = NULL;
7808 rsurface.batchelement3i = NULL;
7809 rsurface.batchelement3i_indexbuffer = NULL;
7810 rsurface.batchelement3i_bufferoffset = 0;
7811 rsurface.batchelement3s = NULL;
7812 rsurface.batchelement3s_indexbuffer = NULL;
7813 rsurface.batchelement3s_bufferoffset = 0;
7814 rsurface.passcolor4f = NULL;
7815 rsurface.passcolor4f_vertexbuffer = NULL;
7816 rsurface.passcolor4f_bufferoffset = 0;
7819 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7821 dp_model_t *model = ent->model;
7822 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7824 rsurface.entity = (entity_render_t *)ent;
7825 rsurface.skeleton = ent->skeleton;
7826 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7827 rsurface.ent_skinnum = ent->skinnum;
7828 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;
7829 rsurface.ent_shadertime = ent->shadertime;
7830 rsurface.ent_flags = ent->flags;
7831 rsurface.matrix = ent->matrix;
7832 rsurface.inversematrix = ent->inversematrix;
7833 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7834 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7835 R_EntityMatrix(&rsurface.matrix);
7836 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7837 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7838 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7839 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7840 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7841 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7842 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7843 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7844 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7845 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7846 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7847 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7848 rsurface.colormod[3] = ent->alpha;
7849 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7850 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7851 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7852 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7853 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7854 if (ent->model->brush.submodel && !prepass)
7856 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7857 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7859 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7861 if (ent->animcache_vertex3f)
7863 rsurface.modelvertex3f = ent->animcache_vertex3f;
7864 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7865 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7866 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7867 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7868 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7869 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7871 else if (wanttangents)
7873 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7874 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7875 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7876 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7877 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7878 rsurface.modelvertexmesh = NULL;
7879 rsurface.modelvertexmeshbuffer = NULL;
7880 rsurface.modelvertex3fbuffer = NULL;
7882 else if (wantnormals)
7884 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7885 rsurface.modelsvector3f = NULL;
7886 rsurface.modeltvector3f = NULL;
7887 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7888 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7889 rsurface.modelvertexmesh = NULL;
7890 rsurface.modelvertexmeshbuffer = NULL;
7891 rsurface.modelvertex3fbuffer = NULL;
7895 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7896 rsurface.modelsvector3f = NULL;
7897 rsurface.modeltvector3f = NULL;
7898 rsurface.modelnormal3f = NULL;
7899 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7900 rsurface.modelvertexmesh = NULL;
7901 rsurface.modelvertexmeshbuffer = NULL;
7902 rsurface.modelvertex3fbuffer = NULL;
7904 rsurface.modelvertex3f_vertexbuffer = 0;
7905 rsurface.modelvertex3f_bufferoffset = 0;
7906 rsurface.modelsvector3f_vertexbuffer = 0;
7907 rsurface.modelsvector3f_bufferoffset = 0;
7908 rsurface.modeltvector3f_vertexbuffer = 0;
7909 rsurface.modeltvector3f_bufferoffset = 0;
7910 rsurface.modelnormal3f_vertexbuffer = 0;
7911 rsurface.modelnormal3f_bufferoffset = 0;
7912 rsurface.modelgeneratedvertex = true;
7916 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7917 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7918 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7919 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7920 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7921 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7922 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7923 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7924 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7925 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7926 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7927 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7928 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7929 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7930 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7931 rsurface.modelgeneratedvertex = false;
7933 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7934 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7935 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7936 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7937 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7938 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7939 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7940 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7941 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7942 rsurface.modelelement3i = model->surfmesh.data_element3i;
7943 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7944 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7945 rsurface.modelelement3s = model->surfmesh.data_element3s;
7946 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7947 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7948 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7949 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7950 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7951 rsurface.modelsurfaces = model->data_surfaces;
7952 rsurface.batchgeneratedvertex = false;
7953 rsurface.batchfirstvertex = 0;
7954 rsurface.batchnumvertices = 0;
7955 rsurface.batchfirsttriangle = 0;
7956 rsurface.batchnumtriangles = 0;
7957 rsurface.batchvertex3f = NULL;
7958 rsurface.batchvertex3f_vertexbuffer = NULL;
7959 rsurface.batchvertex3f_bufferoffset = 0;
7960 rsurface.batchsvector3f = NULL;
7961 rsurface.batchsvector3f_vertexbuffer = NULL;
7962 rsurface.batchsvector3f_bufferoffset = 0;
7963 rsurface.batchtvector3f = NULL;
7964 rsurface.batchtvector3f_vertexbuffer = NULL;
7965 rsurface.batchtvector3f_bufferoffset = 0;
7966 rsurface.batchnormal3f = NULL;
7967 rsurface.batchnormal3f_vertexbuffer = NULL;
7968 rsurface.batchnormal3f_bufferoffset = 0;
7969 rsurface.batchlightmapcolor4f = NULL;
7970 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7971 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7972 rsurface.batchtexcoordtexture2f = NULL;
7973 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7974 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7975 rsurface.batchtexcoordlightmap2f = NULL;
7976 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7977 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7978 rsurface.batchvertexmesh = NULL;
7979 rsurface.batchvertexmeshbuffer = NULL;
7980 rsurface.batchvertex3fbuffer = NULL;
7981 rsurface.batchelement3i = NULL;
7982 rsurface.batchelement3i_indexbuffer = NULL;
7983 rsurface.batchelement3i_bufferoffset = 0;
7984 rsurface.batchelement3s = NULL;
7985 rsurface.batchelement3s_indexbuffer = NULL;
7986 rsurface.batchelement3s_bufferoffset = 0;
7987 rsurface.passcolor4f = NULL;
7988 rsurface.passcolor4f_vertexbuffer = NULL;
7989 rsurface.passcolor4f_bufferoffset = 0;
7992 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)
7994 rsurface.entity = r_refdef.scene.worldentity;
7995 rsurface.skeleton = NULL;
7996 rsurface.ent_skinnum = 0;
7997 rsurface.ent_qwskin = -1;
7998 rsurface.ent_shadertime = shadertime;
7999 rsurface.ent_flags = entflags;
8000 rsurface.modelnumvertices = numvertices;
8001 rsurface.modelnumtriangles = numtriangles;
8002 rsurface.matrix = *matrix;
8003 rsurface.inversematrix = *inversematrix;
8004 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8005 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8006 R_EntityMatrix(&rsurface.matrix);
8007 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8008 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8009 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8010 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8011 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8012 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8013 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8014 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8015 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8016 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8017 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8018 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8019 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);
8020 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8021 rsurface.frameblend[0].lerp = 1;
8022 rsurface.ent_alttextures = false;
8023 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8024 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8027 rsurface.modelvertex3f = (float *)vertex3f;
8028 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8029 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8030 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8032 else if (wantnormals)
8034 rsurface.modelvertex3f = (float *)vertex3f;
8035 rsurface.modelsvector3f = NULL;
8036 rsurface.modeltvector3f = NULL;
8037 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8041 rsurface.modelvertex3f = (float *)vertex3f;
8042 rsurface.modelsvector3f = NULL;
8043 rsurface.modeltvector3f = NULL;
8044 rsurface.modelnormal3f = NULL;
8046 rsurface.modelvertexmesh = NULL;
8047 rsurface.modelvertexmeshbuffer = NULL;
8048 rsurface.modelvertex3fbuffer = NULL;
8049 rsurface.modelvertex3f_vertexbuffer = 0;
8050 rsurface.modelvertex3f_bufferoffset = 0;
8051 rsurface.modelsvector3f_vertexbuffer = 0;
8052 rsurface.modelsvector3f_bufferoffset = 0;
8053 rsurface.modeltvector3f_vertexbuffer = 0;
8054 rsurface.modeltvector3f_bufferoffset = 0;
8055 rsurface.modelnormal3f_vertexbuffer = 0;
8056 rsurface.modelnormal3f_bufferoffset = 0;
8057 rsurface.modelgeneratedvertex = true;
8058 rsurface.modellightmapcolor4f = (float *)color4f;
8059 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8060 rsurface.modellightmapcolor4f_bufferoffset = 0;
8061 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8062 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8063 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8064 rsurface.modeltexcoordlightmap2f = NULL;
8065 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8066 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8067 rsurface.modelelement3i = (int *)element3i;
8068 rsurface.modelelement3i_indexbuffer = NULL;
8069 rsurface.modelelement3i_bufferoffset = 0;
8070 rsurface.modelelement3s = (unsigned short *)element3s;
8071 rsurface.modelelement3s_indexbuffer = NULL;
8072 rsurface.modelelement3s_bufferoffset = 0;
8073 rsurface.modellightmapoffsets = NULL;
8074 rsurface.modelsurfaces = NULL;
8075 rsurface.batchgeneratedvertex = false;
8076 rsurface.batchfirstvertex = 0;
8077 rsurface.batchnumvertices = 0;
8078 rsurface.batchfirsttriangle = 0;
8079 rsurface.batchnumtriangles = 0;
8080 rsurface.batchvertex3f = NULL;
8081 rsurface.batchvertex3f_vertexbuffer = NULL;
8082 rsurface.batchvertex3f_bufferoffset = 0;
8083 rsurface.batchsvector3f = NULL;
8084 rsurface.batchsvector3f_vertexbuffer = NULL;
8085 rsurface.batchsvector3f_bufferoffset = 0;
8086 rsurface.batchtvector3f = NULL;
8087 rsurface.batchtvector3f_vertexbuffer = NULL;
8088 rsurface.batchtvector3f_bufferoffset = 0;
8089 rsurface.batchnormal3f = NULL;
8090 rsurface.batchnormal3f_vertexbuffer = NULL;
8091 rsurface.batchnormal3f_bufferoffset = 0;
8092 rsurface.batchlightmapcolor4f = NULL;
8093 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8094 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8095 rsurface.batchtexcoordtexture2f = NULL;
8096 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8097 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8098 rsurface.batchtexcoordlightmap2f = NULL;
8099 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8100 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8101 rsurface.batchvertexmesh = NULL;
8102 rsurface.batchvertexmeshbuffer = NULL;
8103 rsurface.batchvertex3fbuffer = NULL;
8104 rsurface.batchelement3i = NULL;
8105 rsurface.batchelement3i_indexbuffer = NULL;
8106 rsurface.batchelement3i_bufferoffset = 0;
8107 rsurface.batchelement3s = NULL;
8108 rsurface.batchelement3s_indexbuffer = NULL;
8109 rsurface.batchelement3s_bufferoffset = 0;
8110 rsurface.passcolor4f = NULL;
8111 rsurface.passcolor4f_vertexbuffer = NULL;
8112 rsurface.passcolor4f_bufferoffset = 0;
8114 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8116 if ((wantnormals || wanttangents) && !normal3f)
8118 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8119 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8121 if (wanttangents && !svector3f)
8123 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8124 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8125 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8130 float RSurf_FogPoint(const float *v)
8132 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8133 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8134 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8135 float FogHeightFade = r_refdef.fogheightfade;
8137 unsigned int fogmasktableindex;
8138 if (r_refdef.fogplaneviewabove)
8139 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8141 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8142 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8143 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8146 float RSurf_FogVertex(const float *v)
8148 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8149 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8150 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8151 float FogHeightFade = rsurface.fogheightfade;
8153 unsigned int fogmasktableindex;
8154 if (r_refdef.fogplaneviewabove)
8155 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8157 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8158 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8159 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8162 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8165 for (i = 0;i < numelements;i++)
8166 outelement3i[i] = inelement3i[i] + adjust;
8169 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8170 extern cvar_t gl_vbo;
8171 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8179 int surfacefirsttriangle;
8180 int surfacenumtriangles;
8181 int surfacefirstvertex;
8182 int surfaceendvertex;
8183 int surfacenumvertices;
8184 int batchnumvertices;
8185 int batchnumtriangles;
8189 qboolean dynamicvertex;
8193 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8195 q3shaderinfo_deform_t *deform;
8196 const msurface_t *surface, *firstsurface;
8197 r_vertexmesh_t *vertexmesh;
8198 if (!texturenumsurfaces)
8200 // find vertex range of this surface batch
8202 firstsurface = texturesurfacelist[0];
8203 firsttriangle = firstsurface->num_firsttriangle;
8204 batchnumvertices = 0;
8205 batchnumtriangles = 0;
8206 firstvertex = endvertex = firstsurface->num_firstvertex;
8207 for (i = 0;i < texturenumsurfaces;i++)
8209 surface = texturesurfacelist[i];
8210 if (surface != firstsurface + i)
8212 surfacefirstvertex = surface->num_firstvertex;
8213 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8214 surfacenumvertices = surface->num_vertices;
8215 surfacenumtriangles = surface->num_triangles;
8216 if (firstvertex > surfacefirstvertex)
8217 firstvertex = surfacefirstvertex;
8218 if (endvertex < surfaceendvertex)
8219 endvertex = surfaceendvertex;
8220 batchnumvertices += surfacenumvertices;
8221 batchnumtriangles += surfacenumtriangles;
8224 // we now know the vertex range used, and if there are any gaps in it
8225 rsurface.batchfirstvertex = firstvertex;
8226 rsurface.batchnumvertices = endvertex - firstvertex;
8227 rsurface.batchfirsttriangle = firsttriangle;
8228 rsurface.batchnumtriangles = batchnumtriangles;
8230 // this variable holds flags for which properties have been updated that
8231 // may require regenerating vertexmesh array...
8234 // check if any dynamic vertex processing must occur
8235 dynamicvertex = false;
8237 // if there is a chance of animated vertex colors, it's a dynamic batch
8238 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8240 dynamicvertex = true;
8241 batchneed |= BATCHNEED_NOGAPS;
8242 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8245 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8247 switch (deform->deform)
8250 case Q3DEFORM_PROJECTIONSHADOW:
8251 case Q3DEFORM_TEXT0:
8252 case Q3DEFORM_TEXT1:
8253 case Q3DEFORM_TEXT2:
8254 case Q3DEFORM_TEXT3:
8255 case Q3DEFORM_TEXT4:
8256 case Q3DEFORM_TEXT5:
8257 case Q3DEFORM_TEXT6:
8258 case Q3DEFORM_TEXT7:
8261 case Q3DEFORM_AUTOSPRITE:
8262 dynamicvertex = true;
8263 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8264 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8266 case Q3DEFORM_AUTOSPRITE2:
8267 dynamicvertex = true;
8268 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8269 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8271 case Q3DEFORM_NORMAL:
8272 dynamicvertex = true;
8273 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8274 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8277 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8278 break; // if wavefunc is a nop, ignore this transform
8279 dynamicvertex = true;
8280 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8281 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8283 case Q3DEFORM_BULGE:
8284 dynamicvertex = true;
8285 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8286 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8289 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8290 break; // if wavefunc is a nop, ignore this transform
8291 dynamicvertex = true;
8292 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8293 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8297 switch(rsurface.texture->tcgen.tcgen)
8300 case Q3TCGEN_TEXTURE:
8302 case Q3TCGEN_LIGHTMAP:
8303 dynamicvertex = true;
8304 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8305 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8307 case Q3TCGEN_VECTOR:
8308 dynamicvertex = true;
8309 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8310 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8312 case Q3TCGEN_ENVIRONMENT:
8313 dynamicvertex = true;
8314 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8315 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8318 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8320 dynamicvertex = true;
8321 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8322 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8325 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8327 dynamicvertex = true;
8328 batchneed |= BATCHNEED_NOGAPS;
8329 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8332 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8334 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8335 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8336 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8337 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8338 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8339 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8340 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8343 // when the model data has no vertex buffer (dynamic mesh), we need to
8345 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8346 batchneed |= BATCHNEED_NOGAPS;
8348 // if needsupdate, we have to do a dynamic vertex batch for sure
8349 if (needsupdate & batchneed)
8350 dynamicvertex = true;
8352 // see if we need to build vertexmesh from arrays
8353 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8354 dynamicvertex = true;
8356 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8357 // also some drivers strongly dislike firstvertex
8358 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8359 dynamicvertex = true;
8361 rsurface.batchvertex3f = rsurface.modelvertex3f;
8362 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8363 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8364 rsurface.batchsvector3f = rsurface.modelsvector3f;
8365 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8366 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8367 rsurface.batchtvector3f = rsurface.modeltvector3f;
8368 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8369 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8370 rsurface.batchnormal3f = rsurface.modelnormal3f;
8371 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8372 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8373 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8374 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8375 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8376 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8377 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8378 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8379 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8380 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8381 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8382 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8383 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8384 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8385 rsurface.batchelement3i = rsurface.modelelement3i;
8386 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8387 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8388 rsurface.batchelement3s = rsurface.modelelement3s;
8389 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8390 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8392 // if any dynamic vertex processing has to occur in software, we copy the
8393 // entire surface list together before processing to rebase the vertices
8394 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8396 // if any gaps exist and we do not have a static vertex buffer, we have to
8397 // copy the surface list together to avoid wasting upload bandwidth on the
8398 // vertices in the gaps.
8400 // if gaps exist and we have a static vertex buffer, we still have to
8401 // combine the index buffer ranges into one dynamic index buffer.
8403 // in all cases we end up with data that can be drawn in one call.
8407 // static vertex data, just set pointers...
8408 rsurface.batchgeneratedvertex = false;
8409 // if there are gaps, we want to build a combined index buffer,
8410 // otherwise use the original static buffer with an appropriate offset
8413 // build a new triangle elements array for this batch
8414 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8415 rsurface.batchfirsttriangle = 0;
8417 for (i = 0;i < texturenumsurfaces;i++)
8419 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8420 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8421 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8422 numtriangles += surfacenumtriangles;
8424 rsurface.batchelement3i_indexbuffer = NULL;
8425 rsurface.batchelement3i_bufferoffset = 0;
8426 rsurface.batchelement3s = NULL;
8427 rsurface.batchelement3s_indexbuffer = NULL;
8428 rsurface.batchelement3s_bufferoffset = 0;
8429 if (endvertex <= 65536)
8431 // make a 16bit (unsigned short) index array if possible
8432 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8433 for (i = 0;i < numtriangles*3;i++)
8434 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8440 // something needs software processing, do it for real...
8441 // we only directly handle separate array data in this case and then
8442 // generate interleaved data if needed...
8443 rsurface.batchgeneratedvertex = true;
8445 // now copy the vertex data into a combined array and make an index array
8446 // (this is what Quake3 does all the time)
8447 //if (gaps || rsurface.batchfirstvertex)
8449 rsurface.batchvertex3fbuffer = NULL;
8450 rsurface.batchvertexmesh = NULL;
8451 rsurface.batchvertexmeshbuffer = NULL;
8452 rsurface.batchvertex3f = NULL;
8453 rsurface.batchvertex3f_vertexbuffer = NULL;
8454 rsurface.batchvertex3f_bufferoffset = 0;
8455 rsurface.batchsvector3f = NULL;
8456 rsurface.batchsvector3f_vertexbuffer = NULL;
8457 rsurface.batchsvector3f_bufferoffset = 0;
8458 rsurface.batchtvector3f = NULL;
8459 rsurface.batchtvector3f_vertexbuffer = NULL;
8460 rsurface.batchtvector3f_bufferoffset = 0;
8461 rsurface.batchnormal3f = NULL;
8462 rsurface.batchnormal3f_vertexbuffer = NULL;
8463 rsurface.batchnormal3f_bufferoffset = 0;
8464 rsurface.batchlightmapcolor4f = NULL;
8465 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8466 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8467 rsurface.batchtexcoordtexture2f = NULL;
8468 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8469 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8470 rsurface.batchtexcoordlightmap2f = NULL;
8471 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8472 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8473 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8474 rsurface.batchelement3i_indexbuffer = NULL;
8475 rsurface.batchelement3i_bufferoffset = 0;
8476 rsurface.batchelement3s = NULL;
8477 rsurface.batchelement3s_indexbuffer = NULL;
8478 rsurface.batchelement3s_bufferoffset = 0;
8479 // we'll only be setting up certain arrays as needed
8480 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8481 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8482 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8483 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8484 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8485 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8486 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8488 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8489 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8491 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8492 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8493 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8494 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8495 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8496 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8499 for (i = 0;i < texturenumsurfaces;i++)
8501 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8502 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8503 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8504 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8505 // copy only the data requested
8506 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8507 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8508 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8510 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8511 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8512 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8513 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8514 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8516 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8517 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8519 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8520 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8521 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8522 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8523 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8524 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8526 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8527 numvertices += surfacenumvertices;
8528 numtriangles += surfacenumtriangles;
8531 // generate a 16bit index array as well if possible
8532 // (in general, dynamic batches fit)
8533 if (numvertices <= 65536)
8535 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8536 for (i = 0;i < numtriangles*3;i++)
8537 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8540 // since we've copied everything, the batch now starts at 0
8541 rsurface.batchfirstvertex = 0;
8542 rsurface.batchnumvertices = batchnumvertices;
8543 rsurface.batchfirsttriangle = 0;
8544 rsurface.batchnumtriangles = batchnumtriangles;
8547 // q1bsp surfaces rendered in vertex color mode have to have colors
8548 // calculated based on lightstyles
8549 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8551 // generate color arrays for the surfaces in this list
8556 const unsigned char *lm;
8557 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8558 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8559 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8561 for (i = 0;i < texturenumsurfaces;i++)
8563 surface = texturesurfacelist[i];
8564 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8565 surfacenumvertices = surface->num_vertices;
8566 if (surface->lightmapinfo->samples)
8568 for (j = 0;j < surfacenumvertices;j++)
8570 lm = surface->lightmapinfo->samples + offsets[j];
8571 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8572 VectorScale(lm, scale, c);
8573 if (surface->lightmapinfo->styles[1] != 255)
8575 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8577 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8578 VectorMA(c, scale, lm, c);
8579 if (surface->lightmapinfo->styles[2] != 255)
8582 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8583 VectorMA(c, scale, lm, c);
8584 if (surface->lightmapinfo->styles[3] != 255)
8587 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8588 VectorMA(c, scale, lm, c);
8595 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);
8601 for (j = 0;j < surfacenumvertices;j++)
8603 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8610 // if vertices are deformed (sprite flares and things in maps, possibly
8611 // water waves, bulges and other deformations), modify the copied vertices
8613 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8615 switch (deform->deform)
8618 case Q3DEFORM_PROJECTIONSHADOW:
8619 case Q3DEFORM_TEXT0:
8620 case Q3DEFORM_TEXT1:
8621 case Q3DEFORM_TEXT2:
8622 case Q3DEFORM_TEXT3:
8623 case Q3DEFORM_TEXT4:
8624 case Q3DEFORM_TEXT5:
8625 case Q3DEFORM_TEXT6:
8626 case Q3DEFORM_TEXT7:
8629 case Q3DEFORM_AUTOSPRITE:
8630 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8631 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8632 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8633 VectorNormalize(newforward);
8634 VectorNormalize(newright);
8635 VectorNormalize(newup);
8636 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8637 // rsurface.batchvertex3f_vertexbuffer = NULL;
8638 // rsurface.batchvertex3f_bufferoffset = 0;
8639 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8640 // rsurface.batchsvector3f_vertexbuffer = NULL;
8641 // rsurface.batchsvector3f_bufferoffset = 0;
8642 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8643 // rsurface.batchtvector3f_vertexbuffer = NULL;
8644 // rsurface.batchtvector3f_bufferoffset = 0;
8645 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8646 // rsurface.batchnormal3f_vertexbuffer = NULL;
8647 // rsurface.batchnormal3f_bufferoffset = 0;
8648 // a single autosprite surface can contain multiple sprites...
8649 for (j = 0;j < batchnumvertices - 3;j += 4)
8651 VectorClear(center);
8652 for (i = 0;i < 4;i++)
8653 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8654 VectorScale(center, 0.25f, center);
8655 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8656 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8657 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8658 for (i = 0;i < 4;i++)
8660 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8661 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8664 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8665 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8666 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);
8668 case Q3DEFORM_AUTOSPRITE2:
8669 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8670 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8671 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8672 VectorNormalize(newforward);
8673 VectorNormalize(newright);
8674 VectorNormalize(newup);
8675 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8676 // rsurface.batchvertex3f_vertexbuffer = NULL;
8677 // rsurface.batchvertex3f_bufferoffset = 0;
8679 const float *v1, *v2;
8689 memset(shortest, 0, sizeof(shortest));
8690 // a single autosprite surface can contain multiple sprites...
8691 for (j = 0;j < batchnumvertices - 3;j += 4)
8693 VectorClear(center);
8694 for (i = 0;i < 4;i++)
8695 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8696 VectorScale(center, 0.25f, center);
8697 // find the two shortest edges, then use them to define the
8698 // axis vectors for rotating around the central axis
8699 for (i = 0;i < 6;i++)
8701 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8702 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8703 l = VectorDistance2(v1, v2);
8704 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8706 l += (1.0f / 1024.0f);
8707 if (shortest[0].length2 > l || i == 0)
8709 shortest[1] = shortest[0];
8710 shortest[0].length2 = l;
8711 shortest[0].v1 = v1;
8712 shortest[0].v2 = v2;
8714 else if (shortest[1].length2 > l || i == 1)
8716 shortest[1].length2 = l;
8717 shortest[1].v1 = v1;
8718 shortest[1].v2 = v2;
8721 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8722 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8723 // this calculates the right vector from the shortest edge
8724 // and the up vector from the edge midpoints
8725 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8726 VectorNormalize(right);
8727 VectorSubtract(end, start, up);
8728 VectorNormalize(up);
8729 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8730 VectorSubtract(rsurface.localvieworigin, center, forward);
8731 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8732 VectorNegate(forward, forward);
8733 VectorReflect(forward, 0, up, forward);
8734 VectorNormalize(forward);
8735 CrossProduct(up, forward, newright);
8736 VectorNormalize(newright);
8737 // rotate the quad around the up axis vector, this is made
8738 // especially easy by the fact we know the quad is flat,
8739 // so we only have to subtract the center position and
8740 // measure distance along the right vector, and then
8741 // multiply that by the newright vector and add back the
8743 // we also need to subtract the old position to undo the
8744 // displacement from the center, which we do with a
8745 // DotProduct, the subtraction/addition of center is also
8746 // optimized into DotProducts here
8747 l = DotProduct(right, center);
8748 for (i = 0;i < 4;i++)
8750 v1 = rsurface.batchvertex3f + 3*(j+i);
8751 f = DotProduct(right, v1) - l;
8752 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8756 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8758 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8759 // rsurface.batchnormal3f_vertexbuffer = NULL;
8760 // rsurface.batchnormal3f_bufferoffset = 0;
8761 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8763 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8765 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8766 // rsurface.batchsvector3f_vertexbuffer = NULL;
8767 // rsurface.batchsvector3f_bufferoffset = 0;
8768 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8769 // rsurface.batchtvector3f_vertexbuffer = NULL;
8770 // rsurface.batchtvector3f_bufferoffset = 0;
8771 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);
8774 case Q3DEFORM_NORMAL:
8775 // deform the normals to make reflections wavey
8776 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8777 rsurface.batchnormal3f_vertexbuffer = NULL;
8778 rsurface.batchnormal3f_bufferoffset = 0;
8779 for (j = 0;j < batchnumvertices;j++)
8782 float *normal = rsurface.batchnormal3f + 3*j;
8783 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8784 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8785 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]);
8786 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]);
8787 VectorNormalize(normal);
8789 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8791 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8792 // rsurface.batchsvector3f_vertexbuffer = NULL;
8793 // rsurface.batchsvector3f_bufferoffset = 0;
8794 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8795 // rsurface.batchtvector3f_vertexbuffer = NULL;
8796 // rsurface.batchtvector3f_bufferoffset = 0;
8797 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);
8801 // deform vertex array to make wavey water and flags and such
8802 waveparms[0] = deform->waveparms[0];
8803 waveparms[1] = deform->waveparms[1];
8804 waveparms[2] = deform->waveparms[2];
8805 waveparms[3] = deform->waveparms[3];
8806 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8807 break; // if wavefunc is a nop, don't make a dynamic vertex array
8808 // this is how a divisor of vertex influence on deformation
8809 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8810 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8811 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8812 // rsurface.batchvertex3f_vertexbuffer = NULL;
8813 // rsurface.batchvertex3f_bufferoffset = 0;
8814 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8815 // rsurface.batchnormal3f_vertexbuffer = NULL;
8816 // rsurface.batchnormal3f_bufferoffset = 0;
8817 for (j = 0;j < batchnumvertices;j++)
8819 // if the wavefunc depends on time, evaluate it per-vertex
8822 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8823 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8825 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8827 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8828 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8829 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8831 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8832 // rsurface.batchsvector3f_vertexbuffer = NULL;
8833 // rsurface.batchsvector3f_bufferoffset = 0;
8834 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8835 // rsurface.batchtvector3f_vertexbuffer = NULL;
8836 // rsurface.batchtvector3f_bufferoffset = 0;
8837 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);
8840 case Q3DEFORM_BULGE:
8841 // deform vertex array to make the surface have moving bulges
8842 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8843 // rsurface.batchvertex3f_vertexbuffer = NULL;
8844 // rsurface.batchvertex3f_bufferoffset = 0;
8845 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8846 // rsurface.batchnormal3f_vertexbuffer = NULL;
8847 // rsurface.batchnormal3f_bufferoffset = 0;
8848 for (j = 0;j < batchnumvertices;j++)
8850 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8851 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8853 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8854 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8855 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8857 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8858 // rsurface.batchsvector3f_vertexbuffer = NULL;
8859 // rsurface.batchsvector3f_bufferoffset = 0;
8860 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8861 // rsurface.batchtvector3f_vertexbuffer = NULL;
8862 // rsurface.batchtvector3f_bufferoffset = 0;
8863 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);
8867 // deform vertex array
8868 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8869 break; // if wavefunc is a nop, don't make a dynamic vertex array
8870 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8871 VectorScale(deform->parms, scale, waveparms);
8872 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8873 // rsurface.batchvertex3f_vertexbuffer = NULL;
8874 // rsurface.batchvertex3f_bufferoffset = 0;
8875 for (j = 0;j < batchnumvertices;j++)
8876 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8881 // generate texcoords based on the chosen texcoord source
8882 switch(rsurface.texture->tcgen.tcgen)
8885 case Q3TCGEN_TEXTURE:
8887 case Q3TCGEN_LIGHTMAP:
8888 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8889 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8890 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8891 if (rsurface.batchtexcoordlightmap2f)
8892 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8894 case Q3TCGEN_VECTOR:
8895 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8896 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8897 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8898 for (j = 0;j < batchnumvertices;j++)
8900 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8901 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8904 case Q3TCGEN_ENVIRONMENT:
8905 // make environment reflections using a spheremap
8906 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8907 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8908 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8909 for (j = 0;j < batchnumvertices;j++)
8911 // identical to Q3A's method, but executed in worldspace so
8912 // carried models can be shiny too
8914 float viewer[3], d, reflected[3], worldreflected[3];
8916 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8917 // VectorNormalize(viewer);
8919 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8921 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8922 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8923 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8924 // note: this is proportinal to viewer, so we can normalize later
8926 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8927 VectorNormalize(worldreflected);
8929 // note: this sphere map only uses world x and z!
8930 // so positive and negative y will LOOK THE SAME.
8931 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8932 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8936 // the only tcmod that needs software vertex processing is turbulent, so
8937 // check for it here and apply the changes if needed
8938 // and we only support that as the first one
8939 // (handling a mixture of turbulent and other tcmods would be problematic
8940 // without punting it entirely to a software path)
8941 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8943 amplitude = rsurface.texture->tcmods[0].parms[1];
8944 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8945 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8946 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8947 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8948 for (j = 0;j < batchnumvertices;j++)
8950 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);
8951 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8955 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8957 // convert the modified arrays to vertex structs
8958 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8959 // rsurface.batchvertexmeshbuffer = NULL;
8960 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8961 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8962 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8963 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8964 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8965 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
8966 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
8968 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8970 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
8971 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
8974 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
8975 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8976 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
8977 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
8978 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8979 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
8980 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
8981 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8982 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
8986 void RSurf_DrawBatch(void)
8988 // sometimes a zero triangle surface (usually a degenerate patch) makes it
8989 // through the pipeline, killing it earlier in the pipeline would have
8990 // per-surface overhead rather than per-batch overhead, so it's best to
8991 // reject it here, before it hits glDraw.
8992 if (rsurface.batchnumtriangles == 0)
8995 // batch debugging code
8996 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9002 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9003 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9006 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9008 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9010 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9011 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);
9018 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);
9021 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9023 // pick the closest matching water plane
9024 int planeindex, vertexindex, bestplaneindex = -1;
9028 r_waterstate_waterplane_t *p;
9029 qboolean prepared = false;
9031 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9033 if(p->camera_entity != rsurface.texture->camera_entity)
9038 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9040 if(rsurface.batchnumvertices == 0)
9043 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9045 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9046 d += fabs(PlaneDiff(vert, &p->plane));
9048 if (bestd > d || bestplaneindex < 0)
9051 bestplaneindex = planeindex;
9054 return bestplaneindex;
9055 // NOTE: this MAY return a totally unrelated water plane; we can ignore
9056 // this situation though, as it might be better to render single larger
9057 // batches with useless stuff (backface culled for example) than to
9058 // render multiple smaller batches
9061 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9064 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9065 rsurface.passcolor4f_vertexbuffer = 0;
9066 rsurface.passcolor4f_bufferoffset = 0;
9067 for (i = 0;i < rsurface.batchnumvertices;i++)
9068 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9071 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9078 if (rsurface.passcolor4f)
9080 // generate color arrays
9081 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
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, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
9087 f = RSurf_FogVertex(v);
9096 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9097 rsurface.passcolor4f_vertexbuffer = 0;
9098 rsurface.passcolor4f_bufferoffset = 0;
9099 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9101 f = RSurf_FogVertex(v);
9110 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9117 if (!rsurface.passcolor4f)
9119 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9120 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9121 rsurface.passcolor4f_vertexbuffer = 0;
9122 rsurface.passcolor4f_bufferoffset = 0;
9123 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
9125 f = RSurf_FogVertex(v);
9126 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9127 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9128 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9133 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9138 if (!rsurface.passcolor4f)
9140 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9141 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9142 rsurface.passcolor4f_vertexbuffer = 0;
9143 rsurface.passcolor4f_bufferoffset = 0;
9144 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9153 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9158 if (!rsurface.passcolor4f)
9160 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9161 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9162 rsurface.passcolor4f_vertexbuffer = 0;
9163 rsurface.passcolor4f_bufferoffset = 0;
9164 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9166 c2[0] = c[0] + r_refdef.scene.ambient;
9167 c2[1] = c[1] + r_refdef.scene.ambient;
9168 c2[2] = c[2] + r_refdef.scene.ambient;
9173 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9176 rsurface.passcolor4f = NULL;
9177 rsurface.passcolor4f_vertexbuffer = 0;
9178 rsurface.passcolor4f_bufferoffset = 0;
9179 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9180 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9181 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9182 GL_Color(r, g, b, a);
9183 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9187 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9189 // TODO: optimize applyfog && applycolor case
9190 // just apply fog if necessary, and tint the fog color array if necessary
9191 rsurface.passcolor4f = NULL;
9192 rsurface.passcolor4f_vertexbuffer = 0;
9193 rsurface.passcolor4f_bufferoffset = 0;
9194 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9195 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9196 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9197 GL_Color(r, g, b, a);
9201 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9204 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9205 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9206 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9207 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9208 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9209 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9210 GL_Color(r, g, b, a);
9214 static void RSurf_DrawBatch_GL11_ClampColor(void)
9219 if (!rsurface.passcolor4f)
9221 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9223 c2[0] = bound(0.0f, c1[0], 1.0f);
9224 c2[1] = bound(0.0f, c1[1], 1.0f);
9225 c2[2] = bound(0.0f, c1[2], 1.0f);
9226 c2[3] = bound(0.0f, c1[3], 1.0f);
9230 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9240 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9241 rsurface.passcolor4f_vertexbuffer = 0;
9242 rsurface.passcolor4f_bufferoffset = 0;
9243 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)
9245 f = -DotProduct(r_refdef.view.forward, n);
9247 f = f * 0.85 + 0.15; // work around so stuff won't get black
9248 f *= r_refdef.lightmapintensity;
9249 Vector4Set(c, f, f, f, 1);
9253 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9255 RSurf_DrawBatch_GL11_ApplyFakeLight();
9256 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9257 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9258 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9259 GL_Color(r, g, b, a);
9263 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9271 vec3_t ambientcolor;
9272 vec3_t diffusecolor;
9276 VectorCopy(rsurface.modellight_lightdir, lightdir);
9277 f = 0.5f * r_refdef.lightmapintensity;
9278 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9279 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9280 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9281 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9282 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9283 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9285 if (VectorLength2(diffusecolor) > 0)
9287 // q3-style directional shading
9288 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9289 rsurface.passcolor4f_vertexbuffer = 0;
9290 rsurface.passcolor4f_bufferoffset = 0;
9291 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)
9293 if ((f = DotProduct(n, lightdir)) > 0)
9294 VectorMA(ambientcolor, f, diffusecolor, c);
9296 VectorCopy(ambientcolor, c);
9303 *applycolor = false;
9307 *r = ambientcolor[0];
9308 *g = ambientcolor[1];
9309 *b = ambientcolor[2];
9310 rsurface.passcolor4f = NULL;
9311 rsurface.passcolor4f_vertexbuffer = 0;
9312 rsurface.passcolor4f_bufferoffset = 0;
9316 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9318 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9319 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9320 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9321 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9322 GL_Color(r, g, b, a);
9326 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9334 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9335 rsurface.passcolor4f_vertexbuffer = 0;
9336 rsurface.passcolor4f_bufferoffset = 0;
9338 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9340 f = 1 - RSurf_FogVertex(v);
9348 void RSurf_SetupDepthAndCulling(void)
9350 // submodels are biased to avoid z-fighting with world surfaces that they
9351 // may be exactly overlapping (avoids z-fighting artifacts on certain
9352 // doors and things in Quake maps)
9353 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9354 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9355 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9356 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9359 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9361 // transparent sky would be ridiculous
9362 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9364 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9365 skyrenderlater = true;
9366 RSurf_SetupDepthAndCulling();
9368 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9369 // skymasking on them, and Quake3 never did sky masking (unlike
9370 // software Quake and software Quake2), so disable the sky masking
9371 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9372 // and skymasking also looks very bad when noclipping outside the
9373 // level, so don't use it then either.
9374 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9376 R_Mesh_ResetTextureState();
9377 if (skyrendermasked)
9379 R_SetupShader_DepthOrShadow();
9380 // depth-only (masking)
9381 GL_ColorMask(0,0,0,0);
9382 // just to make sure that braindead drivers don't draw
9383 // anything despite that colormask...
9384 GL_BlendFunc(GL_ZERO, GL_ONE);
9385 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9386 if (rsurface.batchvertex3fbuffer)
9387 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9389 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9393 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9395 GL_BlendFunc(GL_ONE, GL_ZERO);
9396 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9397 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9398 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9401 if (skyrendermasked)
9402 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9404 R_Mesh_ResetTextureState();
9405 GL_Color(1, 1, 1, 1);
9408 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9409 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9410 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9412 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9416 // render screenspace normalmap to texture
9418 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9423 // bind lightmap texture
9425 // water/refraction/reflection/camera surfaces have to be handled specially
9426 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9428 int start, end, startplaneindex;
9429 for (start = 0;start < texturenumsurfaces;start = end)
9431 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9432 if(startplaneindex < 0)
9434 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9435 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9439 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9441 // now that we have a batch using the same planeindex, render it
9442 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9444 // render water or distortion background
9446 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));
9448 // blend surface on top
9449 GL_DepthMask(false);
9450 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9453 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9455 // render surface with reflection texture as input
9456 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9457 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));
9464 // render surface batch normally
9465 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9466 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9470 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9472 // OpenGL 1.3 path - anything not completely ancient
9473 qboolean applycolor;
9476 const texturelayer_t *layer;
9477 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);
9478 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9480 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9483 int layertexrgbscale;
9484 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9486 if (layerindex == 0)
9490 GL_AlphaTest(false);
9491 GL_DepthFunc(GL_EQUAL);
9494 GL_DepthMask(layer->depthmask && writedepth);
9495 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9496 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9498 layertexrgbscale = 4;
9499 VectorScale(layer->color, 0.25f, layercolor);
9501 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9503 layertexrgbscale = 2;
9504 VectorScale(layer->color, 0.5f, layercolor);
9508 layertexrgbscale = 1;
9509 VectorScale(layer->color, 1.0f, layercolor);
9511 layercolor[3] = layer->color[3];
9512 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9513 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9514 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9515 switch (layer->type)
9517 case TEXTURELAYERTYPE_LITTEXTURE:
9518 // single-pass lightmapped texture with 2x rgbscale
9519 R_Mesh_TexBind(0, r_texture_white);
9520 R_Mesh_TexMatrix(0, NULL);
9521 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9522 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9523 R_Mesh_TexBind(1, layer->texture);
9524 R_Mesh_TexMatrix(1, &layer->texmatrix);
9525 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9526 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9527 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9528 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9529 else if (FAKELIGHT_ENABLED)
9530 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9531 else if (rsurface.uselightmaptexture)
9532 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9534 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9536 case TEXTURELAYERTYPE_TEXTURE:
9537 // singletexture unlit texture with transparency support
9538 R_Mesh_TexBind(0, layer->texture);
9539 R_Mesh_TexMatrix(0, &layer->texmatrix);
9540 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9541 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9542 R_Mesh_TexBind(1, 0);
9543 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9544 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9546 case TEXTURELAYERTYPE_FOG:
9547 // singletexture fogging
9550 R_Mesh_TexBind(0, layer->texture);
9551 R_Mesh_TexMatrix(0, &layer->texmatrix);
9552 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9553 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9557 R_Mesh_TexBind(0, 0);
9558 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9560 R_Mesh_TexBind(1, 0);
9561 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9562 // generate a color array for the fog pass
9563 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9564 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9568 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9571 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9573 GL_DepthFunc(GL_LEQUAL);
9574 GL_AlphaTest(false);
9578 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9580 // OpenGL 1.1 - crusty old voodoo path
9583 const texturelayer_t *layer;
9584 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);
9585 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9587 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9589 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9591 if (layerindex == 0)
9595 GL_AlphaTest(false);
9596 GL_DepthFunc(GL_EQUAL);
9599 GL_DepthMask(layer->depthmask && writedepth);
9600 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9601 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9602 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9603 switch (layer->type)
9605 case TEXTURELAYERTYPE_LITTEXTURE:
9606 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9608 // two-pass lit texture with 2x rgbscale
9609 // first the lightmap pass
9610 R_Mesh_TexBind(0, r_texture_white);
9611 R_Mesh_TexMatrix(0, NULL);
9612 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9613 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9614 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9615 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9616 else if (FAKELIGHT_ENABLED)
9617 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9618 else if (rsurface.uselightmaptexture)
9619 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9621 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9622 // then apply the texture to it
9623 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9624 R_Mesh_TexBind(0, layer->texture);
9625 R_Mesh_TexMatrix(0, &layer->texmatrix);
9626 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9627 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9628 RSurf_DrawBatch_GL11_Unlit(layer->color[0] * 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);
9632 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9633 R_Mesh_TexBind(0, layer->texture);
9634 R_Mesh_TexMatrix(0, &layer->texmatrix);
9635 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9636 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9637 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9638 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);
9640 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);
9643 case TEXTURELAYERTYPE_TEXTURE:
9644 // singletexture unlit texture with transparency support
9645 R_Mesh_TexBind(0, layer->texture);
9646 R_Mesh_TexMatrix(0, &layer->texmatrix);
9647 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9648 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9649 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);
9651 case TEXTURELAYERTYPE_FOG:
9652 // singletexture fogging
9655 R_Mesh_TexBind(0, layer->texture);
9656 R_Mesh_TexMatrix(0, &layer->texmatrix);
9657 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9658 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9662 R_Mesh_TexBind(0, 0);
9663 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9665 // generate a color array for the fog pass
9666 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9667 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9671 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9674 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9676 GL_DepthFunc(GL_LEQUAL);
9677 GL_AlphaTest(false);
9681 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9685 r_vertexgeneric_t *batchvertex;
9688 // R_Mesh_ResetTextureState();
9689 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9691 if(rsurface.texture && rsurface.texture->currentskinframe)
9693 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9694 c[3] *= rsurface.texture->currentalpha;
9704 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9706 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9707 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9708 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9711 // brighten it up (as texture value 127 means "unlit")
9712 c[0] *= 2 * r_refdef.view.colorscale;
9713 c[1] *= 2 * r_refdef.view.colorscale;
9714 c[2] *= 2 * r_refdef.view.colorscale;
9716 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9717 c[3] *= r_wateralpha.value;
9719 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9721 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9722 GL_DepthMask(false);
9724 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9726 GL_BlendFunc(GL_ONE, GL_ONE);
9727 GL_DepthMask(false);
9729 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9731 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9732 GL_DepthMask(false);
9734 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9736 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9737 GL_DepthMask(false);
9741 GL_BlendFunc(GL_ONE, GL_ZERO);
9742 GL_DepthMask(writedepth);
9745 if (r_showsurfaces.integer == 3)
9747 rsurface.passcolor4f = NULL;
9749 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9751 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9753 rsurface.passcolor4f = NULL;
9754 rsurface.passcolor4f_vertexbuffer = 0;
9755 rsurface.passcolor4f_bufferoffset = 0;
9757 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9759 qboolean applycolor = true;
9762 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9764 r_refdef.lightmapintensity = 1;
9765 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9766 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9768 else if (FAKELIGHT_ENABLED)
9770 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9772 r_refdef.lightmapintensity = r_fakelight_intensity.value;
9773 RSurf_DrawBatch_GL11_ApplyFakeLight();
9774 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9778 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9780 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9781 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9782 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9785 if(!rsurface.passcolor4f)
9786 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9788 RSurf_DrawBatch_GL11_ApplyAmbient();
9789 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9790 if(r_refdef.fogenabled)
9791 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9792 RSurf_DrawBatch_GL11_ClampColor();
9794 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9795 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9798 else if (!r_refdef.view.showdebug)
9800 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9801 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9802 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9804 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9805 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9807 R_Mesh_PrepareVertices_Generic_Unlock();
9810 else if (r_showsurfaces.integer == 4)
9812 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9813 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9814 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9816 unsigned char c = (vi << 3) * (1.0f / 256.0f);
9817 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9818 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9820 R_Mesh_PrepareVertices_Generic_Unlock();
9823 else if (r_showsurfaces.integer == 2)
9826 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9827 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9828 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9830 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9831 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9832 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9833 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9834 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9835 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9836 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9838 R_Mesh_PrepareVertices_Generic_Unlock();
9839 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9843 int texturesurfaceindex;
9845 const msurface_t *surface;
9846 float surfacecolor4f[4];
9847 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9848 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9850 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9852 surface = texturesurfacelist[texturesurfaceindex];
9853 k = (int)(((size_t)surface) / sizeof(msurface_t));
9854 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9855 for (j = 0;j < surface->num_vertices;j++)
9857 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9858 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9862 R_Mesh_PrepareVertices_Generic_Unlock();
9867 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9870 RSurf_SetupDepthAndCulling();
9871 if (r_showsurfaces.integer)
9873 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9876 switch (vid.renderpath)
9878 case RENDERPATH_GL20:
9879 case RENDERPATH_D3D9:
9880 case RENDERPATH_D3D10:
9881 case RENDERPATH_D3D11:
9882 case RENDERPATH_SOFT:
9883 case RENDERPATH_GLES2:
9884 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9886 case RENDERPATH_GL13:
9887 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9889 case RENDERPATH_GL11:
9890 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9896 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9899 RSurf_SetupDepthAndCulling();
9900 if (r_showsurfaces.integer)
9902 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9905 switch (vid.renderpath)
9907 case RENDERPATH_GL20:
9908 case RENDERPATH_D3D9:
9909 case RENDERPATH_D3D10:
9910 case RENDERPATH_D3D11:
9911 case RENDERPATH_SOFT:
9912 case RENDERPATH_GLES2:
9913 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9915 case RENDERPATH_GL13:
9916 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9918 case RENDERPATH_GL11:
9919 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9925 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9928 int texturenumsurfaces, endsurface;
9930 const msurface_t *surface;
9931 #define MAXBATCH_TRANSPARENTSURFACES 256
9932 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9934 // if the model is static it doesn't matter what value we give for
9935 // wantnormals and wanttangents, so this logic uses only rules applicable
9936 // to a model, knowing that they are meaningless otherwise
9937 if (ent == r_refdef.scene.worldentity)
9938 RSurf_ActiveWorldEntity();
9939 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9940 RSurf_ActiveModelEntity(ent, false, false, false);
9943 switch (vid.renderpath)
9945 case RENDERPATH_GL20:
9946 case RENDERPATH_D3D9:
9947 case RENDERPATH_D3D10:
9948 case RENDERPATH_D3D11:
9949 case RENDERPATH_SOFT:
9950 case RENDERPATH_GLES2:
9951 RSurf_ActiveModelEntity(ent, true, true, false);
9953 case RENDERPATH_GL13:
9954 case RENDERPATH_GL11:
9955 RSurf_ActiveModelEntity(ent, true, false, false);
9960 if (r_transparentdepthmasking.integer)
9962 qboolean setup = false;
9963 for (i = 0;i < numsurfaces;i = j)
9966 surface = rsurface.modelsurfaces + surfacelist[i];
9967 texture = surface->texture;
9968 rsurface.texture = R_GetCurrentTexture(texture);
9969 rsurface.lightmaptexture = NULL;
9970 rsurface.deluxemaptexture = NULL;
9971 rsurface.uselightmaptexture = false;
9972 // scan ahead until we find a different texture
9973 endsurface = min(i + 1024, numsurfaces);
9974 texturenumsurfaces = 0;
9975 texturesurfacelist[texturenumsurfaces++] = surface;
9976 for (;j < endsurface;j++)
9978 surface = rsurface.modelsurfaces + surfacelist[j];
9979 if (texture != surface->texture)
9981 texturesurfacelist[texturenumsurfaces++] = surface;
9983 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9985 // render the range of surfaces as depth
9989 GL_ColorMask(0,0,0,0);
9992 GL_BlendFunc(GL_ONE, GL_ZERO);
9994 // R_Mesh_ResetTextureState();
9995 R_SetupShader_DepthOrShadow();
9997 RSurf_SetupDepthAndCulling();
9998 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9999 if (rsurface.batchvertex3fbuffer)
10000 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10002 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10006 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10009 for (i = 0;i < numsurfaces;i = j)
10012 surface = rsurface.modelsurfaces + surfacelist[i];
10013 texture = surface->texture;
10014 rsurface.texture = R_GetCurrentTexture(texture);
10015 // scan ahead until we find a different texture
10016 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
10017 texturenumsurfaces = 0;
10018 texturesurfacelist[texturenumsurfaces++] = surface;
10019 if(FAKELIGHT_ENABLED)
10021 rsurface.lightmaptexture = NULL;
10022 rsurface.deluxemaptexture = NULL;
10023 rsurface.uselightmaptexture = false;
10024 for (;j < endsurface;j++)
10026 surface = rsurface.modelsurfaces + surfacelist[j];
10027 if (texture != surface->texture)
10029 texturesurfacelist[texturenumsurfaces++] = surface;
10034 rsurface.lightmaptexture = surface->lightmaptexture;
10035 rsurface.deluxemaptexture = surface->deluxemaptexture;
10036 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10037 for (;j < endsurface;j++)
10039 surface = rsurface.modelsurfaces + surfacelist[j];
10040 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10042 texturesurfacelist[texturenumsurfaces++] = surface;
10045 // render the range of surfaces
10046 if (ent == r_refdef.scene.worldentity)
10047 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10049 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10051 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10054 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10056 // transparent surfaces get pushed off into the transparent queue
10057 int surfacelistindex;
10058 const msurface_t *surface;
10059 vec3_t tempcenter, center;
10060 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10062 surface = texturesurfacelist[surfacelistindex];
10063 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10064 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10065 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10066 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10067 if (queueentity->transparent_offset) // transparent offset
10069 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10070 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10071 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10073 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10077 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10079 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10081 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10083 RSurf_SetupDepthAndCulling();
10084 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10085 if (rsurface.batchvertex3fbuffer)
10086 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10088 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10092 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10094 const entity_render_t *queueentity = r_refdef.scene.worldentity;
10097 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10100 if (!rsurface.texture->currentnumlayers)
10102 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10103 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10105 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10107 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10108 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10109 else if (!rsurface.texture->currentnumlayers)
10111 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10113 // in the deferred case, transparent surfaces were queued during prepass
10114 if (!r_shadow_usingdeferredprepass)
10115 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10119 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10120 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10125 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10128 texture_t *texture;
10129 R_FrameData_SetMark();
10130 // break the surface list down into batches by texture and use of lightmapping
10131 for (i = 0;i < numsurfaces;i = j)
10134 // texture is the base texture pointer, rsurface.texture is the
10135 // current frame/skin the texture is directing us to use (for example
10136 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10137 // use skin 1 instead)
10138 texture = surfacelist[i]->texture;
10139 rsurface.texture = R_GetCurrentTexture(texture);
10140 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10142 // if this texture is not the kind we want, skip ahead to the next one
10143 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10147 if(FAKELIGHT_ENABLED || depthonly || prepass)
10149 rsurface.lightmaptexture = NULL;
10150 rsurface.deluxemaptexture = NULL;
10151 rsurface.uselightmaptexture = false;
10152 // simply scan ahead until we find a different texture or lightmap state
10153 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10158 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10159 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10160 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10161 // simply scan ahead until we find a different texture or lightmap state
10162 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10165 // render the range of surfaces
10166 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10168 R_FrameData_ReturnToMark();
10171 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10175 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10178 if (!rsurface.texture->currentnumlayers)
10180 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10181 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10183 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10185 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10186 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10187 else if (!rsurface.texture->currentnumlayers)
10189 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10191 // in the deferred case, transparent surfaces were queued during prepass
10192 if (!r_shadow_usingdeferredprepass)
10193 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10197 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10198 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10203 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10206 texture_t *texture;
10207 R_FrameData_SetMark();
10208 // break the surface list down into batches by texture and use of lightmapping
10209 for (i = 0;i < numsurfaces;i = j)
10212 // texture is the base texture pointer, rsurface.texture is the
10213 // current frame/skin the texture is directing us to use (for example
10214 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10215 // use skin 1 instead)
10216 texture = surfacelist[i]->texture;
10217 rsurface.texture = R_GetCurrentTexture(texture);
10218 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10220 // if this texture is not the kind we want, skip ahead to the next one
10221 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10225 if(FAKELIGHT_ENABLED || depthonly || prepass)
10227 rsurface.lightmaptexture = NULL;
10228 rsurface.deluxemaptexture = NULL;
10229 rsurface.uselightmaptexture = false;
10230 // simply scan ahead until we find a different texture or lightmap state
10231 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10236 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10237 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10238 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10239 // simply scan ahead until we find a different texture or lightmap state
10240 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10243 // render the range of surfaces
10244 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10246 R_FrameData_ReturnToMark();
10249 float locboxvertex3f[6*4*3] =
10251 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10252 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10253 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10254 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10255 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10256 1,0,0, 0,0,0, 0,1,0, 1,1,0
10259 unsigned short locboxelements[6*2*3] =
10264 12,13,14, 12,14,15,
10265 16,17,18, 16,18,19,
10269 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10272 cl_locnode_t *loc = (cl_locnode_t *)ent;
10274 float vertex3f[6*4*3];
10276 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10277 GL_DepthMask(false);
10278 GL_DepthRange(0, 1);
10279 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10280 GL_DepthTest(true);
10281 GL_CullFace(GL_NONE);
10282 R_EntityMatrix(&identitymatrix);
10284 // R_Mesh_ResetTextureState();
10286 i = surfacelist[0];
10287 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10288 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10289 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10290 surfacelist[0] < 0 ? 0.5f : 0.125f);
10292 if (VectorCompare(loc->mins, loc->maxs))
10294 VectorSet(size, 2, 2, 2);
10295 VectorMA(loc->mins, -0.5f, size, mins);
10299 VectorCopy(loc->mins, mins);
10300 VectorSubtract(loc->maxs, loc->mins, size);
10303 for (i = 0;i < 6*4*3;)
10304 for (j = 0;j < 3;j++, i++)
10305 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10307 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10308 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10309 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10312 void R_DrawLocs(void)
10315 cl_locnode_t *loc, *nearestloc;
10317 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10318 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10320 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10321 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10325 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10327 if (decalsystem->decals)
10328 Mem_Free(decalsystem->decals);
10329 memset(decalsystem, 0, sizeof(*decalsystem));
10332 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)
10335 tridecal_t *decals;
10338 // expand or initialize the system
10339 if (decalsystem->maxdecals <= decalsystem->numdecals)
10341 decalsystem_t old = *decalsystem;
10342 qboolean useshortelements;
10343 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10344 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10345 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)));
10346 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10347 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10348 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10349 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10350 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10351 if (decalsystem->numdecals)
10352 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10354 Mem_Free(old.decals);
10355 for (i = 0;i < decalsystem->maxdecals*3;i++)
10356 decalsystem->element3i[i] = i;
10357 if (useshortelements)
10358 for (i = 0;i < decalsystem->maxdecals*3;i++)
10359 decalsystem->element3s[i] = i;
10362 // grab a decal and search for another free slot for the next one
10363 decals = decalsystem->decals;
10364 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10365 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10367 decalsystem->freedecal = i;
10368 if (decalsystem->numdecals <= i)
10369 decalsystem->numdecals = i + 1;
10371 // initialize the decal
10373 decal->triangleindex = triangleindex;
10374 decal->surfaceindex = surfaceindex;
10375 decal->decalsequence = decalsequence;
10376 decal->color4f[0][0] = c0[0];
10377 decal->color4f[0][1] = c0[1];
10378 decal->color4f[0][2] = c0[2];
10379 decal->color4f[0][3] = 1;
10380 decal->color4f[1][0] = c1[0];
10381 decal->color4f[1][1] = c1[1];
10382 decal->color4f[1][2] = c1[2];
10383 decal->color4f[1][3] = 1;
10384 decal->color4f[2][0] = c2[0];
10385 decal->color4f[2][1] = c2[1];
10386 decal->color4f[2][2] = c2[2];
10387 decal->color4f[2][3] = 1;
10388 decal->vertex3f[0][0] = v0[0];
10389 decal->vertex3f[0][1] = v0[1];
10390 decal->vertex3f[0][2] = v0[2];
10391 decal->vertex3f[1][0] = v1[0];
10392 decal->vertex3f[1][1] = v1[1];
10393 decal->vertex3f[1][2] = v1[2];
10394 decal->vertex3f[2][0] = v2[0];
10395 decal->vertex3f[2][1] = v2[1];
10396 decal->vertex3f[2][2] = v2[2];
10397 decal->texcoord2f[0][0] = t0[0];
10398 decal->texcoord2f[0][1] = t0[1];
10399 decal->texcoord2f[1][0] = t1[0];
10400 decal->texcoord2f[1][1] = t1[1];
10401 decal->texcoord2f[2][0] = t2[0];
10402 decal->texcoord2f[2][1] = t2[1];
10405 extern cvar_t cl_decals_bias;
10406 extern cvar_t cl_decals_models;
10407 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10408 // baseparms, parms, temps
10409 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)
10414 const float *vertex3f;
10415 const float *normal3f;
10417 float points[2][9][3];
10424 e = rsurface.modelelement3i + 3*triangleindex;
10426 vertex3f = rsurface.modelvertex3f;
10427 normal3f = rsurface.modelnormal3f;
10431 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10433 index = 3*e[cornerindex];
10434 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10439 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10441 index = 3*e[cornerindex];
10442 VectorCopy(vertex3f + index, v[cornerindex]);
10447 //TriangleNormal(v[0], v[1], v[2], normal);
10448 //if (DotProduct(normal, localnormal) < 0.0f)
10450 // clip by each of the box planes formed from the projection matrix
10451 // if anything survives, we emit the decal
10452 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]);
10455 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]);
10458 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]);
10461 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]);
10464 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]);
10467 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]);
10470 // some part of the triangle survived, so we have to accept it...
10473 // dynamic always uses the original triangle
10475 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10477 index = 3*e[cornerindex];
10478 VectorCopy(vertex3f + index, v[cornerindex]);
10481 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10483 // convert vertex positions to texcoords
10484 Matrix4x4_Transform(projection, v[cornerindex], temp);
10485 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10486 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10487 // calculate distance fade from the projection origin
10488 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10489 f = bound(0.0f, f, 1.0f);
10490 c[cornerindex][0] = r * f;
10491 c[cornerindex][1] = g * f;
10492 c[cornerindex][2] = b * f;
10493 c[cornerindex][3] = 1.0f;
10494 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10497 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);
10499 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10500 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);
10502 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)
10504 matrix4x4_t projection;
10505 decalsystem_t *decalsystem;
10508 const msurface_t *surface;
10509 const msurface_t *surfaces;
10510 const int *surfacelist;
10511 const texture_t *texture;
10513 int numsurfacelist;
10514 int surfacelistindex;
10517 float localorigin[3];
10518 float localnormal[3];
10519 float localmins[3];
10520 float localmaxs[3];
10523 float planes[6][4];
10526 int bih_triangles_count;
10527 int bih_triangles[256];
10528 int bih_surfaces[256];
10530 decalsystem = &ent->decalsystem;
10531 model = ent->model;
10532 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10534 R_DecalSystem_Reset(&ent->decalsystem);
10538 if (!model->brush.data_leafs && !cl_decals_models.integer)
10540 if (decalsystem->model)
10541 R_DecalSystem_Reset(decalsystem);
10545 if (decalsystem->model != model)
10546 R_DecalSystem_Reset(decalsystem);
10547 decalsystem->model = model;
10549 RSurf_ActiveModelEntity(ent, true, false, false);
10551 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10552 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10553 VectorNormalize(localnormal);
10554 localsize = worldsize*rsurface.inversematrixscale;
10555 localmins[0] = localorigin[0] - localsize;
10556 localmins[1] = localorigin[1] - localsize;
10557 localmins[2] = localorigin[2] - localsize;
10558 localmaxs[0] = localorigin[0] + localsize;
10559 localmaxs[1] = localorigin[1] + localsize;
10560 localmaxs[2] = localorigin[2] + localsize;
10562 //VectorCopy(localnormal, planes[4]);
10563 //VectorVectors(planes[4], planes[2], planes[0]);
10564 AnglesFromVectors(angles, localnormal, NULL, false);
10565 AngleVectors(angles, planes[0], planes[2], planes[4]);
10566 VectorNegate(planes[0], planes[1]);
10567 VectorNegate(planes[2], planes[3]);
10568 VectorNegate(planes[4], planes[5]);
10569 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10570 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10571 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10572 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10573 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10574 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10579 matrix4x4_t forwardprojection;
10580 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10581 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10586 float projectionvector[4][3];
10587 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10588 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10589 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10590 projectionvector[0][0] = planes[0][0] * ilocalsize;
10591 projectionvector[0][1] = planes[1][0] * ilocalsize;
10592 projectionvector[0][2] = planes[2][0] * ilocalsize;
10593 projectionvector[1][0] = planes[0][1] * ilocalsize;
10594 projectionvector[1][1] = planes[1][1] * ilocalsize;
10595 projectionvector[1][2] = planes[2][1] * ilocalsize;
10596 projectionvector[2][0] = planes[0][2] * ilocalsize;
10597 projectionvector[2][1] = planes[1][2] * ilocalsize;
10598 projectionvector[2][2] = planes[2][2] * ilocalsize;
10599 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10600 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10601 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10602 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10606 dynamic = model->surfmesh.isanimated;
10607 numsurfacelist = model->nummodelsurfaces;
10608 surfacelist = model->sortedmodelsurfaces;
10609 surfaces = model->data_surfaces;
10612 bih_triangles_count = -1;
10615 if(model->render_bih.numleafs)
10616 bih = &model->render_bih;
10617 else if(model->collision_bih.numleafs)
10618 bih = &model->collision_bih;
10621 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10622 if(bih_triangles_count == 0)
10624 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10626 if(bih_triangles_count > 0)
10628 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10630 surfaceindex = bih_surfaces[triangleindex];
10631 surface = surfaces + surfaceindex;
10632 texture = surface->texture;
10633 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10635 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10637 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10642 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10644 surfaceindex = surfacelist[surfacelistindex];
10645 surface = surfaces + surfaceindex;
10646 // check cull box first because it rejects more than any other check
10647 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10649 // skip transparent surfaces
10650 texture = surface->texture;
10651 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10653 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10655 numtriangles = surface->num_triangles;
10656 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10657 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10662 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10663 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)
10665 int renderentityindex;
10666 float worldmins[3];
10667 float worldmaxs[3];
10668 entity_render_t *ent;
10670 if (!cl_decals_newsystem.integer)
10673 worldmins[0] = worldorigin[0] - worldsize;
10674 worldmins[1] = worldorigin[1] - worldsize;
10675 worldmins[2] = worldorigin[2] - worldsize;
10676 worldmaxs[0] = worldorigin[0] + worldsize;
10677 worldmaxs[1] = worldorigin[1] + worldsize;
10678 worldmaxs[2] = worldorigin[2] + worldsize;
10680 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10682 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10684 ent = r_refdef.scene.entities[renderentityindex];
10685 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10688 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10692 typedef struct r_decalsystem_splatqueue_s
10694 vec3_t worldorigin;
10695 vec3_t worldnormal;
10701 r_decalsystem_splatqueue_t;
10703 int r_decalsystem_numqueued = 0;
10704 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10706 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)
10708 r_decalsystem_splatqueue_t *queue;
10710 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10713 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10714 VectorCopy(worldorigin, queue->worldorigin);
10715 VectorCopy(worldnormal, queue->worldnormal);
10716 Vector4Set(queue->color, r, g, b, a);
10717 Vector4Set(queue->tcrange, s1, t1, s2, t2);
10718 queue->worldsize = worldsize;
10719 queue->decalsequence = cl.decalsequence++;
10722 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10725 r_decalsystem_splatqueue_t *queue;
10727 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10728 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);
10729 r_decalsystem_numqueued = 0;
10732 extern cvar_t cl_decals_max;
10733 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10736 decalsystem_t *decalsystem = &ent->decalsystem;
10743 if (!decalsystem->numdecals)
10746 if (r_showsurfaces.integer)
10749 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10751 R_DecalSystem_Reset(decalsystem);
10755 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10756 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10758 if (decalsystem->lastupdatetime)
10759 frametime = (cl.time - decalsystem->lastupdatetime);
10762 decalsystem->lastupdatetime = cl.time;
10763 decal = decalsystem->decals;
10764 numdecals = decalsystem->numdecals;
10766 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10768 if (decal->color4f[0][3])
10770 decal->lived += frametime;
10771 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10773 memset(decal, 0, sizeof(*decal));
10774 if (decalsystem->freedecal > i)
10775 decalsystem->freedecal = i;
10779 decal = decalsystem->decals;
10780 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10783 // collapse the array by shuffling the tail decals into the gaps
10786 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10787 decalsystem->freedecal++;
10788 if (decalsystem->freedecal == numdecals)
10790 decal[decalsystem->freedecal] = decal[--numdecals];
10793 decalsystem->numdecals = numdecals;
10795 if (numdecals <= 0)
10797 // if there are no decals left, reset decalsystem
10798 R_DecalSystem_Reset(decalsystem);
10802 extern skinframe_t *decalskinframe;
10803 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10806 decalsystem_t *decalsystem = &ent->decalsystem;
10815 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10818 numdecals = decalsystem->numdecals;
10822 if (r_showsurfaces.integer)
10825 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10827 R_DecalSystem_Reset(decalsystem);
10831 // if the model is static it doesn't matter what value we give for
10832 // wantnormals and wanttangents, so this logic uses only rules applicable
10833 // to a model, knowing that they are meaningless otherwise
10834 if (ent == r_refdef.scene.worldentity)
10835 RSurf_ActiveWorldEntity();
10837 RSurf_ActiveModelEntity(ent, false, false, false);
10839 decalsystem->lastupdatetime = cl.time;
10840 decal = decalsystem->decals;
10842 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10844 // update vertex positions for animated models
10845 v3f = decalsystem->vertex3f;
10846 c4f = decalsystem->color4f;
10847 t2f = decalsystem->texcoord2f;
10848 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10850 if (!decal->color4f[0][3])
10853 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10856 // update color values for fading decals
10857 if (decal->lived >= cl_decals_time.value)
10858 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10862 c4f[ 0] = decal->color4f[0][0] * alpha;
10863 c4f[ 1] = decal->color4f[0][1] * alpha;
10864 c4f[ 2] = decal->color4f[0][2] * alpha;
10866 c4f[ 4] = decal->color4f[1][0] * alpha;
10867 c4f[ 5] = decal->color4f[1][1] * alpha;
10868 c4f[ 6] = decal->color4f[1][2] * alpha;
10870 c4f[ 8] = decal->color4f[2][0] * alpha;
10871 c4f[ 9] = decal->color4f[2][1] * alpha;
10872 c4f[10] = decal->color4f[2][2] * alpha;
10875 t2f[0] = decal->texcoord2f[0][0];
10876 t2f[1] = decal->texcoord2f[0][1];
10877 t2f[2] = decal->texcoord2f[1][0];
10878 t2f[3] = decal->texcoord2f[1][1];
10879 t2f[4] = decal->texcoord2f[2][0];
10880 t2f[5] = decal->texcoord2f[2][1];
10882 // update vertex positions for animated models
10883 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10885 e = rsurface.modelelement3i + 3*decal->triangleindex;
10886 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10887 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10888 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10892 VectorCopy(decal->vertex3f[0], v3f);
10893 VectorCopy(decal->vertex3f[1], v3f + 3);
10894 VectorCopy(decal->vertex3f[2], v3f + 6);
10897 if (r_refdef.fogenabled)
10899 alpha = RSurf_FogVertex(v3f);
10900 VectorScale(c4f, alpha, c4f);
10901 alpha = RSurf_FogVertex(v3f + 3);
10902 VectorScale(c4f + 4, alpha, c4f + 4);
10903 alpha = RSurf_FogVertex(v3f + 6);
10904 VectorScale(c4f + 8, alpha, c4f + 8);
10915 r_refdef.stats.drawndecals += numtris;
10917 // now render the decals all at once
10918 // (this assumes they all use one particle font texture!)
10919 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);
10920 // R_Mesh_ResetTextureState();
10921 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10922 GL_DepthMask(false);
10923 GL_DepthRange(0, 1);
10924 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10925 GL_DepthTest(true);
10926 GL_CullFace(GL_NONE);
10927 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10928 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10929 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10933 static void R_DrawModelDecals(void)
10937 // fade faster when there are too many decals
10938 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10939 for (i = 0;i < r_refdef.scene.numentities;i++)
10940 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10942 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10943 for (i = 0;i < r_refdef.scene.numentities;i++)
10944 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10945 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10947 R_DecalSystem_ApplySplatEntitiesQueue();
10949 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10950 for (i = 0;i < r_refdef.scene.numentities;i++)
10951 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10953 r_refdef.stats.totaldecals += numdecals;
10955 if (r_showsurfaces.integer)
10958 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10960 for (i = 0;i < r_refdef.scene.numentities;i++)
10962 if (!r_refdef.viewcache.entityvisible[i])
10964 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10965 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10969 extern cvar_t mod_collision_bih;
10970 void R_DrawDebugModel(void)
10972 entity_render_t *ent = rsurface.entity;
10973 int i, j, k, l, flagsmask;
10974 const msurface_t *surface;
10975 dp_model_t *model = ent->model;
10978 switch(vid.renderpath)
10980 case RENDERPATH_GL11:
10981 case RENDERPATH_GL13:
10982 case RENDERPATH_GL20:
10984 case RENDERPATH_D3D9:
10985 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10987 case RENDERPATH_D3D10:
10988 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10990 case RENDERPATH_D3D11:
10991 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10993 case RENDERPATH_SOFT:
10994 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10996 case RENDERPATH_GLES2:
10997 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
11001 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11003 // R_Mesh_ResetTextureState();
11004 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11005 GL_DepthRange(0, 1);
11006 GL_DepthTest(!r_showdisabledepthtest.integer);
11007 GL_DepthMask(false);
11008 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11010 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11014 qboolean cullbox = ent == r_refdef.scene.worldentity;
11015 const q3mbrush_t *brush;
11016 const bih_t *bih = &model->collision_bih;
11017 const bih_leaf_t *bihleaf;
11018 float vertex3f[3][3];
11019 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11021 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11023 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11025 switch (bihleaf->type)
11028 brush = model->brush.data_brushes + bihleaf->itemindex;
11029 if (brush->colbrushf && brush->colbrushf->numtriangles)
11031 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);
11032 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11033 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11036 case BIH_COLLISIONTRIANGLE:
11037 triangleindex = bihleaf->itemindex;
11038 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11039 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11040 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11041 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);
11042 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11043 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11045 case BIH_RENDERTRIANGLE:
11046 triangleindex = bihleaf->itemindex;
11047 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11048 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11049 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11050 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);
11051 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11052 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11058 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11060 if (r_showtris.integer || (r_shownormals.value != 0))
11062 if (r_showdisabledepthtest.integer)
11064 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11065 GL_DepthMask(false);
11069 GL_BlendFunc(GL_ONE, GL_ZERO);
11070 GL_DepthMask(true);
11072 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11074 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11076 rsurface.texture = R_GetCurrentTexture(surface->texture);
11077 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11079 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11080 if (r_showtris.value > 0)
11082 if (!rsurface.texture->currentlayers->depthmask)
11083 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11084 else if (ent == r_refdef.scene.worldentity)
11085 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11087 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11088 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11089 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
11091 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
11094 if (r_shownormals.value < 0)
11096 qglBegin(GL_LINES);
11097 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11099 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11100 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11101 qglVertex3f(v[0], v[1], v[2]);
11102 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11103 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11104 qglVertex3f(v[0], v[1], v[2]);
11109 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11111 qglBegin(GL_LINES);
11112 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11114 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11115 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11116 qglVertex3f(v[0], v[1], v[2]);
11117 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11118 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11119 qglVertex3f(v[0], v[1], v[2]);
11123 qglBegin(GL_LINES);
11124 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11126 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11127 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11128 qglVertex3f(v[0], v[1], v[2]);
11129 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11130 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11131 qglVertex3f(v[0], v[1], v[2]);
11135 qglBegin(GL_LINES);
11136 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11138 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11139 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11140 qglVertex3f(v[0], v[1], v[2]);
11141 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11142 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11143 qglVertex3f(v[0], v[1], v[2]);
11150 rsurface.texture = NULL;
11154 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11155 int r_maxsurfacelist = 0;
11156 const msurface_t **r_surfacelist = NULL;
11157 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11159 int i, j, endj, flagsmask;
11160 dp_model_t *model = r_refdef.scene.worldmodel;
11161 msurface_t *surfaces;
11162 unsigned char *update;
11163 int numsurfacelist = 0;
11167 if (r_maxsurfacelist < model->num_surfaces)
11169 r_maxsurfacelist = model->num_surfaces;
11171 Mem_Free((msurface_t**)r_surfacelist);
11172 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11175 RSurf_ActiveWorldEntity();
11177 surfaces = model->data_surfaces;
11178 update = model->brushq1.lightmapupdateflags;
11180 // update light styles on this submodel
11181 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11183 model_brush_lightstyleinfo_t *style;
11184 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11186 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11188 int *list = style->surfacelist;
11189 style->value = r_refdef.scene.lightstylevalue[style->style];
11190 for (j = 0;j < style->numsurfaces;j++)
11191 update[list[j]] = true;
11196 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11200 R_DrawDebugModel();
11201 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11205 rsurface.lightmaptexture = NULL;
11206 rsurface.deluxemaptexture = NULL;
11207 rsurface.uselightmaptexture = false;
11208 rsurface.texture = NULL;
11209 rsurface.rtlight = NULL;
11210 numsurfacelist = 0;
11211 // add visible surfaces to draw list
11212 for (i = 0;i < model->nummodelsurfaces;i++)
11214 j = model->sortedmodelsurfaces[i];
11215 if (r_refdef.viewcache.world_surfacevisible[j])
11216 r_surfacelist[numsurfacelist++] = surfaces + j;
11218 // update lightmaps if needed
11219 if (model->brushq1.firstrender)
11221 model->brushq1.firstrender = false;
11222 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11224 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11228 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11229 if (r_refdef.viewcache.world_surfacevisible[j])
11231 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11233 // don't do anything if there were no surfaces
11234 if (!numsurfacelist)
11236 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11239 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11241 // add to stats if desired
11242 if (r_speeds.integer && !skysurfaces && !depthonly)
11244 r_refdef.stats.world_surfaces += numsurfacelist;
11245 for (j = 0;j < numsurfacelist;j++)
11246 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11249 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11252 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11254 int i, j, endj, flagsmask;
11255 dp_model_t *model = ent->model;
11256 msurface_t *surfaces;
11257 unsigned char *update;
11258 int numsurfacelist = 0;
11262 if (r_maxsurfacelist < model->num_surfaces)
11264 r_maxsurfacelist = model->num_surfaces;
11266 Mem_Free((msurface_t **)r_surfacelist);
11267 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11270 // if the model is static it doesn't matter what value we give for
11271 // wantnormals and wanttangents, so this logic uses only rules applicable
11272 // to a model, knowing that they are meaningless otherwise
11273 if (ent == r_refdef.scene.worldentity)
11274 RSurf_ActiveWorldEntity();
11275 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11276 RSurf_ActiveModelEntity(ent, false, false, false);
11278 RSurf_ActiveModelEntity(ent, true, true, true);
11279 else if (depthonly)
11281 switch (vid.renderpath)
11283 case RENDERPATH_GL20:
11284 case RENDERPATH_D3D9:
11285 case RENDERPATH_D3D10:
11286 case RENDERPATH_D3D11:
11287 case RENDERPATH_SOFT:
11288 case RENDERPATH_GLES2:
11289 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11291 case RENDERPATH_GL13:
11292 case RENDERPATH_GL11:
11293 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11299 switch (vid.renderpath)
11301 case RENDERPATH_GL20:
11302 case RENDERPATH_D3D9:
11303 case RENDERPATH_D3D10:
11304 case RENDERPATH_D3D11:
11305 case RENDERPATH_SOFT:
11306 case RENDERPATH_GLES2:
11307 RSurf_ActiveModelEntity(ent, true, true, false);
11309 case RENDERPATH_GL13:
11310 case RENDERPATH_GL11:
11311 RSurf_ActiveModelEntity(ent, true, false, false);
11316 surfaces = model->data_surfaces;
11317 update = model->brushq1.lightmapupdateflags;
11319 // update light styles
11320 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11322 model_brush_lightstyleinfo_t *style;
11323 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11325 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11327 int *list = style->surfacelist;
11328 style->value = r_refdef.scene.lightstylevalue[style->style];
11329 for (j = 0;j < style->numsurfaces;j++)
11330 update[list[j]] = true;
11335 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11339 R_DrawDebugModel();
11340 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11344 rsurface.lightmaptexture = NULL;
11345 rsurface.deluxemaptexture = NULL;
11346 rsurface.uselightmaptexture = false;
11347 rsurface.texture = NULL;
11348 rsurface.rtlight = NULL;
11349 numsurfacelist = 0;
11350 // add visible surfaces to draw list
11351 for (i = 0;i < model->nummodelsurfaces;i++)
11352 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11353 // don't do anything if there were no surfaces
11354 if (!numsurfacelist)
11356 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11359 // update lightmaps if needed
11363 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11368 R_BuildLightMap(ent, surfaces + j);
11373 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11375 R_BuildLightMap(ent, surfaces + j);
11376 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11378 // add to stats if desired
11379 if (r_speeds.integer && !skysurfaces && !depthonly)
11381 r_refdef.stats.entities_surfaces += numsurfacelist;
11382 for (j = 0;j < numsurfacelist;j++)
11383 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11386 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11389 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11391 static texture_t texture;
11392 static msurface_t surface;
11393 const msurface_t *surfacelist = &surface;
11395 // fake enough texture and surface state to render this geometry
11397 texture.update_lastrenderframe = -1; // regenerate this texture
11398 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11399 texture.currentskinframe = skinframe;
11400 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11401 texture.offsetmapping = OFFSETMAPPING_OFF;
11402 texture.offsetscale = 1;
11403 texture.specularscalemod = 1;
11404 texture.specularpowermod = 1;
11406 surface.texture = &texture;
11407 surface.num_triangles = numtriangles;
11408 surface.num_firsttriangle = firsttriangle;
11409 surface.num_vertices = numvertices;
11410 surface.num_firstvertex = firstvertex;
11413 rsurface.texture = R_GetCurrentTexture(surface.texture);
11414 rsurface.lightmaptexture = NULL;
11415 rsurface.deluxemaptexture = NULL;
11416 rsurface.uselightmaptexture = false;
11417 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11420 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)
11422 static msurface_t surface;
11423 const msurface_t *surfacelist = &surface;
11425 // fake enough texture and surface state to render this geometry
11426 surface.texture = texture;
11427 surface.num_triangles = numtriangles;
11428 surface.num_firsttriangle = firsttriangle;
11429 surface.num_vertices = numvertices;
11430 surface.num_firstvertex = firstvertex;
11433 rsurface.texture = R_GetCurrentTexture(surface.texture);
11434 rsurface.lightmaptexture = NULL;
11435 rsurface.deluxemaptexture = NULL;
11436 rsurface.uselightmaptexture = false;
11437 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);