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.0625", "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", "70", "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 case RENDERPATH_GLES2:
3844 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3845 Cvar_SetValueQuick(&gl_combine, 1);
3846 Cvar_SetValueQuick(&r_glsl, 1);
3847 r_loadnormalmap = true;
3851 case RENDERPATH_GL13:
3852 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3853 Cvar_SetValueQuick(&gl_combine, 1);
3854 Cvar_SetValueQuick(&r_glsl, 0);
3855 r_loadnormalmap = false;
3856 r_loadgloss = false;
3859 case RENDERPATH_GL11:
3860 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3861 Cvar_SetValueQuick(&gl_combine, 0);
3862 Cvar_SetValueQuick(&r_glsl, 0);
3863 r_loadnormalmap = false;
3864 r_loadgloss = false;
3870 R_FrameData_Reset();
3874 memset(r_queries, 0, sizeof(r_queries));
3876 r_qwskincache = NULL;
3877 r_qwskincache_size = 0;
3879 // due to caching of texture_t references, the collision cache must be reset
3880 Collision_Cache_Reset(true);
3882 // set up r_skinframe loading system for textures
3883 memset(&r_skinframe, 0, sizeof(r_skinframe));
3884 r_skinframe.loadsequence = 1;
3885 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3887 r_main_texturepool = R_AllocTexturePool();
3888 R_BuildBlankTextures();
3890 if (vid.support.arb_texture_cube_map)
3893 R_BuildNormalizationCube();
3895 r_texture_fogattenuation = NULL;
3896 r_texture_fogheighttexture = NULL;
3897 r_texture_gammaramps = NULL;
3898 //r_texture_fogintensity = NULL;
3899 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3900 memset(&r_waterstate, 0, sizeof(r_waterstate));
3901 r_glsl_permutation = NULL;
3902 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3903 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3904 glslshaderstring = NULL;
3906 r_hlsl_permutation = NULL;
3907 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3908 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3910 hlslshaderstring = NULL;
3911 memset(&r_svbsp, 0, sizeof (r_svbsp));
3913 r_refdef.fogmasktable_density = 0;
3916 void gl_main_shutdown(void)
3919 R_FrameData_Reset();
3921 R_Main_FreeViewCache();
3923 switch(vid.renderpath)
3925 case RENDERPATH_GL11:
3926 case RENDERPATH_GL13:
3927 case RENDERPATH_GL20:
3928 case RENDERPATH_GLES2:
3930 qglDeleteQueriesARB(r_maxqueries, r_queries);
3932 case RENDERPATH_D3D9:
3933 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3935 case RENDERPATH_D3D10:
3936 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3938 case RENDERPATH_D3D11:
3939 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3941 case RENDERPATH_SOFT:
3947 memset(r_queries, 0, sizeof(r_queries));
3949 r_qwskincache = NULL;
3950 r_qwskincache_size = 0;
3952 // clear out the r_skinframe state
3953 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3954 memset(&r_skinframe, 0, sizeof(r_skinframe));
3957 Mem_Free(r_svbsp.nodes);
3958 memset(&r_svbsp, 0, sizeof (r_svbsp));
3959 R_FreeTexturePool(&r_main_texturepool);
3960 loadingscreentexture = NULL;
3961 r_texture_blanknormalmap = NULL;
3962 r_texture_white = NULL;
3963 r_texture_grey128 = NULL;
3964 r_texture_black = NULL;
3965 r_texture_whitecube = NULL;
3966 r_texture_normalizationcube = NULL;
3967 r_texture_fogattenuation = NULL;
3968 r_texture_fogheighttexture = NULL;
3969 r_texture_gammaramps = NULL;
3970 r_texture_numcubemaps = 0;
3971 //r_texture_fogintensity = NULL;
3972 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3973 memset(&r_waterstate, 0, sizeof(r_waterstate));
3976 r_glsl_permutation = NULL;
3977 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3978 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3979 glslshaderstring = NULL;
3981 r_hlsl_permutation = NULL;
3982 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3983 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3985 hlslshaderstring = NULL;
3988 extern void CL_ParseEntityLump(char *entitystring);
3989 void gl_main_newmap(void)
3991 // FIXME: move this code to client
3992 char *entities, entname[MAX_QPATH];
3994 Mem_Free(r_qwskincache);
3995 r_qwskincache = NULL;
3996 r_qwskincache_size = 0;
3999 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4000 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4002 CL_ParseEntityLump(entities);
4006 if (cl.worldmodel->brush.entities)
4007 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4009 R_Main_FreeViewCache();
4011 R_FrameData_Reset();
4014 void GL_Main_Init(void)
4016 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4018 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4019 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4020 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4021 if (gamemode == GAME_NEHAHRA)
4023 Cvar_RegisterVariable (&gl_fogenable);
4024 Cvar_RegisterVariable (&gl_fogdensity);
4025 Cvar_RegisterVariable (&gl_fogred);
4026 Cvar_RegisterVariable (&gl_foggreen);
4027 Cvar_RegisterVariable (&gl_fogblue);
4028 Cvar_RegisterVariable (&gl_fogstart);
4029 Cvar_RegisterVariable (&gl_fogend);
4030 Cvar_RegisterVariable (&gl_skyclip);
4032 Cvar_RegisterVariable(&r_motionblur);
4033 Cvar_RegisterVariable(&r_motionblur_maxblur);
4034 Cvar_RegisterVariable(&r_motionblur_bmin);
4035 Cvar_RegisterVariable(&r_motionblur_vmin);
4036 Cvar_RegisterVariable(&r_motionblur_vmax);
4037 Cvar_RegisterVariable(&r_motionblur_vcoeff);
4038 Cvar_RegisterVariable(&r_motionblur_randomize);
4039 Cvar_RegisterVariable(&r_damageblur);
4040 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4041 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4042 Cvar_RegisterVariable(&r_equalize_entities_by);
4043 Cvar_RegisterVariable(&r_equalize_entities_to);
4044 Cvar_RegisterVariable(&r_depthfirst);
4045 Cvar_RegisterVariable(&r_useinfinitefarclip);
4046 Cvar_RegisterVariable(&r_farclip_base);
4047 Cvar_RegisterVariable(&r_farclip_world);
4048 Cvar_RegisterVariable(&r_nearclip);
4049 Cvar_RegisterVariable(&r_showbboxes);
4050 Cvar_RegisterVariable(&r_showsurfaces);
4051 Cvar_RegisterVariable(&r_showtris);
4052 Cvar_RegisterVariable(&r_shownormals);
4053 Cvar_RegisterVariable(&r_showlighting);
4054 Cvar_RegisterVariable(&r_showshadowvolumes);
4055 Cvar_RegisterVariable(&r_showcollisionbrushes);
4056 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4057 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4058 Cvar_RegisterVariable(&r_showdisabledepthtest);
4059 Cvar_RegisterVariable(&r_drawportals);
4060 Cvar_RegisterVariable(&r_drawentities);
4061 Cvar_RegisterVariable(&r_draw2d);
4062 Cvar_RegisterVariable(&r_drawworld);
4063 Cvar_RegisterVariable(&r_cullentities_trace);
4064 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4065 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4066 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4067 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4068 Cvar_RegisterVariable(&r_drawviewmodel);
4069 Cvar_RegisterVariable(&r_drawexteriormodel);
4070 Cvar_RegisterVariable(&r_speeds);
4071 Cvar_RegisterVariable(&r_fullbrights);
4072 Cvar_RegisterVariable(&r_wateralpha);
4073 Cvar_RegisterVariable(&r_dynamic);
4074 Cvar_RegisterVariable(&r_fakelight);
4075 Cvar_RegisterVariable(&r_fakelight_intensity);
4076 Cvar_RegisterVariable(&r_fullbright);
4077 Cvar_RegisterVariable(&r_shadows);
4078 Cvar_RegisterVariable(&r_shadows_darken);
4079 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4080 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4081 Cvar_RegisterVariable(&r_shadows_throwdistance);
4082 Cvar_RegisterVariable(&r_shadows_throwdirection);
4083 Cvar_RegisterVariable(&r_shadows_focus);
4084 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4085 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4086 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4087 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4088 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4089 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4090 Cvar_RegisterVariable(&r_fog_exp2);
4091 Cvar_RegisterVariable(&r_fog_clear);
4092 Cvar_RegisterVariable(&r_drawfog);
4093 Cvar_RegisterVariable(&r_transparentdepthmasking);
4094 Cvar_RegisterVariable(&r_texture_dds_load);
4095 Cvar_RegisterVariable(&r_texture_dds_save);
4096 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
4097 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
4098 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
4099 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
4100 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
4101 Cvar_RegisterVariable(&r_textureunits);
4102 Cvar_RegisterVariable(&gl_combine);
4103 Cvar_RegisterVariable(&r_viewfbo);
4104 Cvar_RegisterVariable(&r_viewscale);
4105 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4106 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4107 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4108 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4109 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4110 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4111 Cvar_RegisterVariable(&r_glsl);
4112 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4113 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4114 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4115 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4116 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4117 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4118 Cvar_RegisterVariable(&r_glsl_postprocess);
4119 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4120 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4121 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4122 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4123 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4124 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4125 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4126 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4128 Cvar_RegisterVariable(&r_water);
4129 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4130 Cvar_RegisterVariable(&r_water_clippingplanebias);
4131 Cvar_RegisterVariable(&r_water_refractdistort);
4132 Cvar_RegisterVariable(&r_water_reflectdistort);
4133 Cvar_RegisterVariable(&r_water_scissormode);
4134 Cvar_RegisterVariable(&r_lerpsprites);
4135 Cvar_RegisterVariable(&r_lerpmodels);
4136 Cvar_RegisterVariable(&r_lerplightstyles);
4137 Cvar_RegisterVariable(&r_waterscroll);
4138 Cvar_RegisterVariable(&r_bloom);
4139 Cvar_RegisterVariable(&r_bloom_colorscale);
4140 Cvar_RegisterVariable(&r_bloom_brighten);
4141 Cvar_RegisterVariable(&r_bloom_blur);
4142 Cvar_RegisterVariable(&r_bloom_resolution);
4143 Cvar_RegisterVariable(&r_bloom_colorexponent);
4144 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4145 Cvar_RegisterVariable(&r_hdr);
4146 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4147 Cvar_RegisterVariable(&r_hdr_glowintensity);
4148 Cvar_RegisterVariable(&r_hdr_range);
4149 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4150 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4151 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4152 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4153 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4154 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4155 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4156 Cvar_RegisterVariable(&developer_texturelogging);
4157 Cvar_RegisterVariable(&gl_lightmaps);
4158 Cvar_RegisterVariable(&r_test);
4159 Cvar_RegisterVariable(&r_glsl_saturation);
4160 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4161 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4162 Cvar_RegisterVariable(&r_framedatasize);
4163 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4164 Cvar_SetValue("r_fullbrights", 0);
4165 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4167 Cvar_RegisterVariable(&r_track_sprites);
4168 Cvar_RegisterVariable(&r_track_sprites_flags);
4169 Cvar_RegisterVariable(&r_track_sprites_scalew);
4170 Cvar_RegisterVariable(&r_track_sprites_scaleh);
4171 Cvar_RegisterVariable(&r_overheadsprites_perspective);
4172 Cvar_RegisterVariable(&r_overheadsprites_pushback);
4173 Cvar_RegisterVariable(&r_overheadsprites_scalex);
4174 Cvar_RegisterVariable(&r_overheadsprites_scaley);
4177 extern void R_Textures_Init(void);
4178 extern void GL_Draw_Init(void);
4179 extern void GL_Main_Init(void);
4180 extern void R_Shadow_Init(void);
4181 extern void R_Sky_Init(void);
4182 extern void GL_Surf_Init(void);
4183 extern void R_Particles_Init(void);
4184 extern void R_Explosion_Init(void);
4185 extern void gl_backend_init(void);
4186 extern void Sbar_Init(void);
4187 extern void R_LightningBeams_Init(void);
4188 extern void Mod_RenderInit(void);
4189 extern void Font_Init(void);
4191 void Render_Init(void)
4204 R_LightningBeams_Init();
4213 extern char *ENGINE_EXTENSIONS;
4216 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4217 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4218 gl_version = (const char *)qglGetString(GL_VERSION);
4219 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4223 if (!gl_platformextensions)
4224 gl_platformextensions = "";
4226 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4227 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4228 Con_Printf("GL_VERSION: %s\n", gl_version);
4229 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4230 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4232 VID_CheckExtensions();
4234 // LordHavoc: report supported extensions
4235 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4237 // clear to black (loading plaque will be seen over this)
4238 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4241 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4245 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4247 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4250 p = r_refdef.view.frustum + i;
4255 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4259 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4263 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4267 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4271 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4275 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4279 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4283 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4291 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4295 for (i = 0;i < numplanes;i++)
4302 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4306 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4310 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4314 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4318 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4322 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4326 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4330 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4338 //==================================================================================
4340 // LordHavoc: this stores temporary data used within the same frame
4342 typedef struct r_framedata_mem_s
4344 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4345 size_t size; // how much usable space
4346 size_t current; // how much space in use
4347 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4348 size_t wantedsize; // how much space was allocated
4349 unsigned char *data; // start of real data (16byte aligned)
4353 static r_framedata_mem_t *r_framedata_mem;
4355 void R_FrameData_Reset(void)
4357 while (r_framedata_mem)
4359 r_framedata_mem_t *next = r_framedata_mem->purge;
4360 Mem_Free(r_framedata_mem);
4361 r_framedata_mem = next;
4365 void R_FrameData_Resize(void)
4368 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4369 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4370 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4372 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4373 newmem->wantedsize = wantedsize;
4374 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4375 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4376 newmem->current = 0;
4378 newmem->purge = r_framedata_mem;
4379 r_framedata_mem = newmem;
4383 void R_FrameData_NewFrame(void)
4385 R_FrameData_Resize();
4386 if (!r_framedata_mem)
4388 // if we ran out of space on the last frame, free the old memory now
4389 while (r_framedata_mem->purge)
4391 // repeatedly remove the second item in the list, leaving only head
4392 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4393 Mem_Free(r_framedata_mem->purge);
4394 r_framedata_mem->purge = next;
4396 // reset the current mem pointer
4397 r_framedata_mem->current = 0;
4398 r_framedata_mem->mark = 0;
4401 void *R_FrameData_Alloc(size_t size)
4405 // align to 16 byte boundary - the data pointer is already aligned, so we
4406 // only need to ensure the size of every allocation is also aligned
4407 size = (size + 15) & ~15;
4409 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4411 // emergency - we ran out of space, allocate more memory
4412 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4413 R_FrameData_Resize();
4416 data = r_framedata_mem->data + r_framedata_mem->current;
4417 r_framedata_mem->current += size;
4419 // count the usage for stats
4420 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4421 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4423 return (void *)data;
4426 void *R_FrameData_Store(size_t size, void *data)
4428 void *d = R_FrameData_Alloc(size);
4430 memcpy(d, data, size);
4434 void R_FrameData_SetMark(void)
4436 if (!r_framedata_mem)
4438 r_framedata_mem->mark = r_framedata_mem->current;
4441 void R_FrameData_ReturnToMark(void)
4443 if (!r_framedata_mem)
4445 r_framedata_mem->current = r_framedata_mem->mark;
4448 //==================================================================================
4450 // LordHavoc: animcache originally written by Echon, rewritten since then
4453 * Animation cache prevents re-generating mesh data for an animated model
4454 * multiple times in one frame for lighting, shadowing, reflections, etc.
4457 void R_AnimCache_Free(void)
4461 void R_AnimCache_ClearCache(void)
4464 entity_render_t *ent;
4466 for (i = 0;i < r_refdef.scene.numentities;i++)
4468 ent = r_refdef.scene.entities[i];
4469 ent->animcache_vertex3f = NULL;
4470 ent->animcache_normal3f = NULL;
4471 ent->animcache_svector3f = NULL;
4472 ent->animcache_tvector3f = NULL;
4473 ent->animcache_vertexmesh = NULL;
4474 ent->animcache_vertex3fbuffer = NULL;
4475 ent->animcache_vertexmeshbuffer = NULL;
4479 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4483 // check if we need the meshbuffers
4484 if (!vid.useinterleavedarrays)
4487 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4488 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4489 // TODO: upload vertex3f buffer?
4490 if (ent->animcache_vertexmesh)
4492 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4493 for (i = 0;i < numvertices;i++)
4494 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4495 if (ent->animcache_svector3f)
4496 for (i = 0;i < numvertices;i++)
4497 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4498 if (ent->animcache_tvector3f)
4499 for (i = 0;i < numvertices;i++)
4500 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4501 if (ent->animcache_normal3f)
4502 for (i = 0;i < numvertices;i++)
4503 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4504 // TODO: upload vertexmeshbuffer?
4508 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4510 dp_model_t *model = ent->model;
4512 // see if it's already cached this frame
4513 if (ent->animcache_vertex3f)
4515 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4516 if (wantnormals || wanttangents)
4518 if (ent->animcache_normal3f)
4519 wantnormals = false;
4520 if (ent->animcache_svector3f)
4521 wanttangents = false;
4522 if (wantnormals || wanttangents)
4524 numvertices = model->surfmesh.num_vertices;
4526 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4529 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4530 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4532 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4533 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4539 // see if this ent is worth caching
4540 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4542 // get some memory for this entity and generate mesh data
4543 numvertices = model->surfmesh.num_vertices;
4544 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4546 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4549 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4550 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4552 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4553 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4558 void R_AnimCache_CacheVisibleEntities(void)
4561 qboolean wantnormals = true;
4562 qboolean wanttangents = !r_showsurfaces.integer;
4564 switch(vid.renderpath)
4566 case RENDERPATH_GL20:
4567 case RENDERPATH_D3D9:
4568 case RENDERPATH_D3D10:
4569 case RENDERPATH_D3D11:
4570 case RENDERPATH_GLES2:
4572 case RENDERPATH_GL13:
4573 case RENDERPATH_GL11:
4574 wanttangents = false;
4576 case RENDERPATH_SOFT:
4580 if (r_shownormals.integer)
4581 wanttangents = wantnormals = true;
4583 // TODO: thread this
4584 // NOTE: R_PrepareRTLights() also caches entities
4586 for (i = 0;i < r_refdef.scene.numentities;i++)
4587 if (r_refdef.viewcache.entityvisible[i])
4588 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4591 //==================================================================================
4593 static void R_View_UpdateEntityLighting (void)
4596 entity_render_t *ent;
4597 vec3_t tempdiffusenormal, avg;
4598 vec_t f, fa, fd, fdd;
4599 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4601 for (i = 0;i < r_refdef.scene.numentities;i++)
4603 ent = r_refdef.scene.entities[i];
4605 // skip unseen models
4606 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4610 if (ent->model && ent->model->brush.num_leafs)
4612 // TODO: use modellight for r_ambient settings on world?
4613 VectorSet(ent->modellight_ambient, 0, 0, 0);
4614 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4615 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4619 // fetch the lighting from the worldmodel data
4620 VectorClear(ent->modellight_ambient);
4621 VectorClear(ent->modellight_diffuse);
4622 VectorClear(tempdiffusenormal);
4623 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4626 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4628 // complete lightning for lit sprites
4629 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4630 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4632 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4633 org[2] = org[2] + r_overheadsprites_pushback.value;
4634 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4637 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4639 if(ent->flags & RENDER_EQUALIZE)
4641 // first fix up ambient lighting...
4642 if(r_equalize_entities_minambient.value > 0)
4644 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4647 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4648 if(fa < r_equalize_entities_minambient.value * fd)
4651 // fa'/fd' = minambient
4652 // fa'+0.25*fd' = fa+0.25*fd
4654 // fa' = fd' * minambient
4655 // fd'*(0.25+minambient) = fa+0.25*fd
4657 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4658 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4660 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4661 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
4662 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4663 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4668 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4670 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4671 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4675 // adjust brightness and saturation to target
4676 avg[0] = avg[1] = avg[2] = fa / f;
4677 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4678 avg[0] = avg[1] = avg[2] = fd / f;
4679 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4685 VectorSet(ent->modellight_ambient, 1, 1, 1);
4687 // move the light direction into modelspace coordinates for lighting code
4688 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4689 if(VectorLength2(ent->modellight_lightdir) == 0)
4690 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4691 VectorNormalize(ent->modellight_lightdir);
4695 #define MAX_LINEOFSIGHTTRACES 64
4697 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4700 vec3_t boxmins, boxmaxs;
4703 dp_model_t *model = r_refdef.scene.worldmodel;
4705 if (!model || !model->brush.TraceLineOfSight)
4708 // expand the box a little
4709 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4710 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4711 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4712 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4713 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4714 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4716 // return true if eye is inside enlarged box
4717 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4721 VectorCopy(eye, start);
4722 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4723 if (model->brush.TraceLineOfSight(model, start, end))
4726 // try various random positions
4727 for (i = 0;i < numsamples;i++)
4729 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4730 if (model->brush.TraceLineOfSight(model, start, end))
4738 static void R_View_UpdateEntityVisible (void)
4743 entity_render_t *ent;
4745 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4746 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4747 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
4748 : RENDER_EXTERIORMODEL;
4749 if (!r_drawviewmodel.integer)
4750 renderimask |= RENDER_VIEWMODEL;
4751 if (!r_drawexteriormodel.integer)
4752 renderimask |= RENDER_EXTERIORMODEL;
4753 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4755 // worldmodel can check visibility
4756 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4757 for (i = 0;i < r_refdef.scene.numentities;i++)
4759 ent = r_refdef.scene.entities[i];
4760 if (!(ent->flags & renderimask))
4761 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)))
4762 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))
4763 r_refdef.viewcache.entityvisible[i] = true;
4765 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4766 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4768 for (i = 0;i < r_refdef.scene.numentities;i++)
4770 ent = r_refdef.scene.entities[i];
4771 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4773 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4775 continue; // temp entities do pvs only
4776 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4777 ent->last_trace_visibility = realtime;
4778 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4779 r_refdef.viewcache.entityvisible[i] = 0;
4786 // no worldmodel or it can't check visibility
4787 for (i = 0;i < r_refdef.scene.numentities;i++)
4789 ent = r_refdef.scene.entities[i];
4790 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));
4795 /// only used if skyrendermasked, and normally returns false
4796 int R_DrawBrushModelsSky (void)
4799 entity_render_t *ent;
4802 for (i = 0;i < r_refdef.scene.numentities;i++)
4804 if (!r_refdef.viewcache.entityvisible[i])
4806 ent = r_refdef.scene.entities[i];
4807 if (!ent->model || !ent->model->DrawSky)
4809 ent->model->DrawSky(ent);
4815 static void R_DrawNoModel(entity_render_t *ent);
4816 static void R_DrawModels(void)
4819 entity_render_t *ent;
4821 for (i = 0;i < r_refdef.scene.numentities;i++)
4823 if (!r_refdef.viewcache.entityvisible[i])
4825 ent = r_refdef.scene.entities[i];
4826 r_refdef.stats.entities++;
4827 if (ent->model && ent->model->Draw != NULL)
4828 ent->model->Draw(ent);
4834 static void R_DrawModelsDepth(void)
4837 entity_render_t *ent;
4839 for (i = 0;i < r_refdef.scene.numentities;i++)
4841 if (!r_refdef.viewcache.entityvisible[i])
4843 ent = r_refdef.scene.entities[i];
4844 if (ent->model && ent->model->DrawDepth != NULL)
4845 ent->model->DrawDepth(ent);
4849 static void R_DrawModelsDebug(void)
4852 entity_render_t *ent;
4854 for (i = 0;i < r_refdef.scene.numentities;i++)
4856 if (!r_refdef.viewcache.entityvisible[i])
4858 ent = r_refdef.scene.entities[i];
4859 if (ent->model && ent->model->DrawDebug != NULL)
4860 ent->model->DrawDebug(ent);
4864 static void R_DrawModelsAddWaterPlanes(void)
4867 entity_render_t *ent;
4869 for (i = 0;i < r_refdef.scene.numentities;i++)
4871 if (!r_refdef.viewcache.entityvisible[i])
4873 ent = r_refdef.scene.entities[i];
4874 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4875 ent->model->DrawAddWaterPlanes(ent);
4879 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4881 if (r_hdr_irisadaptation.integer)
4885 vec3_t diffusenormal;
4890 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4891 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4892 brightness = max(0.0000001f, brightness);
4893 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4894 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4895 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4896 current = r_hdr_irisadaptation_value.value;
4898 current = min(current + adjust, goal);
4899 else if (current > goal)
4900 current = max(current - adjust, goal);
4901 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4902 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4904 else if (r_hdr_irisadaptation_value.value != 1.0f)
4905 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4908 static void R_View_SetFrustum(const int *scissor)
4911 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4912 vec3_t forward, left, up, origin, v;
4916 // flipped x coordinates (because x points left here)
4917 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4918 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4920 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4921 switch(vid.renderpath)
4923 case RENDERPATH_D3D9:
4924 case RENDERPATH_D3D10:
4925 case RENDERPATH_D3D11:
4926 // non-flipped y coordinates
4927 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4928 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4930 case RENDERPATH_SOFT:
4931 case RENDERPATH_GL11:
4932 case RENDERPATH_GL13:
4933 case RENDERPATH_GL20:
4934 case RENDERPATH_GLES2:
4935 // non-flipped y coordinates
4936 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4937 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4942 // we can't trust r_refdef.view.forward and friends in reflected scenes
4943 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4946 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4947 r_refdef.view.frustum[0].normal[1] = 0 - 0;
4948 r_refdef.view.frustum[0].normal[2] = -1 - 0;
4949 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4950 r_refdef.view.frustum[1].normal[1] = 0 + 0;
4951 r_refdef.view.frustum[1].normal[2] = -1 + 0;
4952 r_refdef.view.frustum[2].normal[0] = 0 - 0;
4953 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4954 r_refdef.view.frustum[2].normal[2] = -1 - 0;
4955 r_refdef.view.frustum[3].normal[0] = 0 + 0;
4956 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4957 r_refdef.view.frustum[3].normal[2] = -1 + 0;
4961 zNear = r_refdef.nearclip;
4962 nudge = 1.0 - 1.0 / (1<<23);
4963 r_refdef.view.frustum[4].normal[0] = 0 - 0;
4964 r_refdef.view.frustum[4].normal[1] = 0 - 0;
4965 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4966 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4967 r_refdef.view.frustum[5].normal[0] = 0 + 0;
4968 r_refdef.view.frustum[5].normal[1] = 0 + 0;
4969 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4970 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4976 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4977 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4978 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4979 r_refdef.view.frustum[0].dist = m[15] - m[12];
4981 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4982 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4983 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4984 r_refdef.view.frustum[1].dist = m[15] + m[12];
4986 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4987 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4988 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4989 r_refdef.view.frustum[2].dist = m[15] - m[13];
4991 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4992 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4993 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4994 r_refdef.view.frustum[3].dist = m[15] + m[13];
4996 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4997 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4998 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4999 r_refdef.view.frustum[4].dist = m[15] - m[14];
5001 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5002 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5003 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5004 r_refdef.view.frustum[5].dist = m[15] + m[14];
5007 if (r_refdef.view.useperspective)
5009 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5010 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]);
5011 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]);
5012 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]);
5013 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]);
5015 // then the normals from the corners relative to origin
5016 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5017 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5018 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5019 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5021 // in a NORMAL view, forward cross left == up
5022 // in a REFLECTED view, forward cross left == down
5023 // so our cross products above need to be adjusted for a left handed coordinate system
5024 CrossProduct(forward, left, v);
5025 if(DotProduct(v, up) < 0)
5027 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5028 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5029 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5030 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5033 // Leaving those out was a mistake, those were in the old code, and they
5034 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5035 // I couldn't reproduce it after adding those normalizations. --blub
5036 VectorNormalize(r_refdef.view.frustum[0].normal);
5037 VectorNormalize(r_refdef.view.frustum[1].normal);
5038 VectorNormalize(r_refdef.view.frustum[2].normal);
5039 VectorNormalize(r_refdef.view.frustum[3].normal);
5041 // make the corners absolute
5042 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5043 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5044 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5045 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5048 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5050 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5051 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5052 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5053 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5054 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5058 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5059 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5060 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5061 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5062 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5063 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5064 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5065 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5066 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5067 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5069 r_refdef.view.numfrustumplanes = 5;
5071 if (r_refdef.view.useclipplane)
5073 r_refdef.view.numfrustumplanes = 6;
5074 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5077 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5078 PlaneClassify(r_refdef.view.frustum + i);
5080 // LordHavoc: note to all quake engine coders, Quake had a special case
5081 // for 90 degrees which assumed a square view (wrong), so I removed it,
5082 // Quake2 has it disabled as well.
5084 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5085 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5086 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5087 //PlaneClassify(&frustum[0]);
5089 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5090 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5091 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5092 //PlaneClassify(&frustum[1]);
5094 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5095 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5096 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5097 //PlaneClassify(&frustum[2]);
5099 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5100 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5101 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5102 //PlaneClassify(&frustum[3]);
5105 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5106 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5107 //PlaneClassify(&frustum[4]);
5110 void R_View_UpdateWithScissor(const int *myscissor)
5112 R_Main_ResizeViewCache();
5113 R_View_SetFrustum(myscissor);
5114 R_View_WorldVisibility(r_refdef.view.useclipplane);
5115 R_View_UpdateEntityVisible();
5116 R_View_UpdateEntityLighting();
5119 void R_View_Update(void)
5121 R_Main_ResizeViewCache();
5122 R_View_SetFrustum(NULL);
5123 R_View_WorldVisibility(r_refdef.view.useclipplane);
5124 R_View_UpdateEntityVisible();
5125 R_View_UpdateEntityLighting();
5128 float viewscalefpsadjusted = 1.0f;
5130 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5132 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5133 scale = bound(0.03125f, scale, 1.0f);
5134 *outwidth = (int)ceil(width * scale);
5135 *outheight = (int)ceil(height * scale);
5138 void R_Mesh_SetMainRenderTargets(void)
5140 if (r_bloomstate.fbo_framebuffer)
5141 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5143 R_Mesh_ResetRenderTargets();
5146 void R_SetupView(qboolean allowwaterclippingplane)
5148 const float *customclipplane = NULL;
5150 int scaledwidth, scaledheight;
5151 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5153 // LordHavoc: couldn't figure out how to make this approach the
5154 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5155 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5156 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5157 dist = r_refdef.view.clipplane.dist;
5158 plane[0] = r_refdef.view.clipplane.normal[0];
5159 plane[1] = r_refdef.view.clipplane.normal[1];
5160 plane[2] = r_refdef.view.clipplane.normal[2];
5162 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5165 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5166 if (!r_refdef.view.useperspective)
5167 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);
5168 else if (vid.stencil && r_useinfinitefarclip.integer)
5169 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);
5171 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);
5172 R_Mesh_SetMainRenderTargets();
5173 R_SetViewport(&r_refdef.view.viewport);
5174 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5176 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5177 float screenplane[4];
5178 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5179 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5180 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5181 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5182 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5186 void R_EntityMatrix(const matrix4x4_t *matrix)
5188 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5190 gl_modelmatrixchanged = false;
5191 gl_modelmatrix = *matrix;
5192 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5193 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5194 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5195 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5197 switch(vid.renderpath)
5199 case RENDERPATH_D3D9:
5201 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5202 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5205 case RENDERPATH_D3D10:
5206 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5208 case RENDERPATH_D3D11:
5209 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5211 case RENDERPATH_GL13:
5212 case RENDERPATH_GL11:
5213 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5215 case RENDERPATH_SOFT:
5216 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5217 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5219 case RENDERPATH_GL20:
5220 case RENDERPATH_GLES2:
5221 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5222 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5228 void R_ResetViewRendering2D(void)
5230 r_viewport_t viewport;
5233 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5234 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);
5235 R_Mesh_ResetRenderTargets();
5236 R_SetViewport(&viewport);
5237 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5238 GL_Color(1, 1, 1, 1);
5239 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5240 GL_BlendFunc(GL_ONE, GL_ZERO);
5241 GL_ScissorTest(false);
5242 GL_DepthMask(false);
5243 GL_DepthRange(0, 1);
5244 GL_DepthTest(false);
5245 GL_DepthFunc(GL_LEQUAL);
5246 R_EntityMatrix(&identitymatrix);
5247 R_Mesh_ResetTextureState();
5248 GL_PolygonOffset(0, 0);
5249 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5250 switch(vid.renderpath)
5252 case RENDERPATH_GL11:
5253 case RENDERPATH_GL13:
5254 case RENDERPATH_GL20:
5255 case RENDERPATH_GLES2:
5256 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5258 case RENDERPATH_D3D9:
5259 case RENDERPATH_D3D10:
5260 case RENDERPATH_D3D11:
5261 case RENDERPATH_SOFT:
5264 GL_CullFace(GL_NONE);
5267 void R_ResetViewRendering3D(void)
5272 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5273 GL_Color(1, 1, 1, 1);
5274 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5275 GL_BlendFunc(GL_ONE, GL_ZERO);
5276 GL_ScissorTest(true);
5278 GL_DepthRange(0, 1);
5280 GL_DepthFunc(GL_LEQUAL);
5281 R_EntityMatrix(&identitymatrix);
5282 R_Mesh_ResetTextureState();
5283 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5284 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5285 switch(vid.renderpath)
5287 case RENDERPATH_GL11:
5288 case RENDERPATH_GL13:
5289 case RENDERPATH_GL20:
5290 case RENDERPATH_GLES2:
5291 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5293 case RENDERPATH_D3D9:
5294 case RENDERPATH_D3D10:
5295 case RENDERPATH_D3D11:
5296 case RENDERPATH_SOFT:
5299 GL_CullFace(r_refdef.view.cullface_back);
5304 R_RenderView_UpdateViewVectors
5307 static void R_RenderView_UpdateViewVectors(void)
5309 // break apart the view matrix into vectors for various purposes
5310 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5311 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5312 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5313 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5314 // make an inverted copy of the view matrix for tracking sprites
5315 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5318 void R_RenderScene(void);
5319 void R_RenderWaterPlanes(void);
5321 static void R_Water_StartFrame(void)
5324 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5325 r_waterstate_waterplane_t *p;
5327 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5330 switch(vid.renderpath)
5332 case RENDERPATH_GL20:
5333 case RENDERPATH_D3D9:
5334 case RENDERPATH_D3D10:
5335 case RENDERPATH_D3D11:
5336 case RENDERPATH_SOFT:
5337 case RENDERPATH_GLES2:
5339 case RENDERPATH_GL13:
5340 case RENDERPATH_GL11:
5344 // set waterwidth and waterheight to the water resolution that will be
5345 // used (often less than the screen resolution for faster rendering)
5346 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5347 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5349 // calculate desired texture sizes
5350 // can't use water if the card does not support the texture size
5351 if (!r_water.integer || r_showsurfaces.integer)
5352 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5353 else if (vid.support.arb_texture_non_power_of_two)
5355 texturewidth = waterwidth;
5356 textureheight = waterheight;
5357 camerawidth = waterwidth;
5358 cameraheight = waterheight;
5362 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5363 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5364 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5365 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5368 // allocate textures as needed
5369 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5371 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5372 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5374 if (p->texture_refraction)
5375 R_FreeTexture(p->texture_refraction);
5376 p->texture_refraction = NULL;
5377 if (p->texture_reflection)
5378 R_FreeTexture(p->texture_reflection);
5379 p->texture_reflection = NULL;
5380 if (p->texture_camera)
5381 R_FreeTexture(p->texture_camera);
5382 p->texture_camera = NULL;
5384 memset(&r_waterstate, 0, sizeof(r_waterstate));
5385 r_waterstate.texturewidth = texturewidth;
5386 r_waterstate.textureheight = textureheight;
5387 r_waterstate.camerawidth = camerawidth;
5388 r_waterstate.cameraheight = cameraheight;
5391 if (r_waterstate.texturewidth)
5393 r_waterstate.enabled = true;
5395 // when doing a reduced render (HDR) we want to use a smaller area
5396 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5397 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5399 // set up variables that will be used in shader setup
5400 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5401 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5402 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5403 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5406 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5407 r_waterstate.numwaterplanes = 0;
5410 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5412 int triangleindex, planeindex;
5418 r_waterstate_waterplane_t *p;
5419 texture_t *t = R_GetCurrentTexture(surface->texture);
5421 // just use the first triangle with a valid normal for any decisions
5422 VectorClear(normal);
5423 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5425 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5426 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5427 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5428 TriangleNormal(vert[0], vert[1], vert[2], normal);
5429 if (VectorLength2(normal) >= 0.001)
5433 VectorCopy(normal, plane.normal);
5434 VectorNormalize(plane.normal);
5435 plane.dist = DotProduct(vert[0], plane.normal);
5436 PlaneClassify(&plane);
5437 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5439 // skip backfaces (except if nocullface is set)
5440 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5442 VectorNegate(plane.normal, plane.normal);
5444 PlaneClassify(&plane);
5448 // find a matching plane if there is one
5449 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5450 if(p->camera_entity == t->camera_entity)
5451 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5453 if (planeindex >= r_waterstate.maxwaterplanes)
5454 return; // nothing we can do, out of planes
5456 // if this triangle does not fit any known plane rendered this frame, add one
5457 if (planeindex >= r_waterstate.numwaterplanes)
5459 // store the new plane
5460 r_waterstate.numwaterplanes++;
5462 // clear materialflags and pvs
5463 p->materialflags = 0;
5464 p->pvsvalid = false;
5465 p->camera_entity = t->camera_entity;
5466 VectorCopy(surface->mins, p->mins);
5467 VectorCopy(surface->maxs, p->maxs);
5472 p->mins[0] = min(p->mins[0], surface->mins[0]);
5473 p->mins[1] = min(p->mins[1], surface->mins[1]);
5474 p->mins[2] = min(p->mins[2], surface->mins[2]);
5475 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5476 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5477 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5479 // merge this surface's materialflags into the waterplane
5480 p->materialflags |= t->currentmaterialflags;
5481 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5483 // merge this surface's PVS into the waterplane
5484 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5485 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5486 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5488 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5494 static void R_Water_ProcessPlanes(void)
5497 r_refdef_view_t originalview;
5498 r_refdef_view_t myview;
5500 r_waterstate_waterplane_t *p;
5503 originalview = r_refdef.view;
5505 // make sure enough textures are allocated
5506 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5508 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5510 if (!p->texture_refraction)
5511 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);
5512 if (!p->texture_refraction)
5515 else if (p->materialflags & MATERIALFLAG_CAMERA)
5517 if (!p->texture_camera)
5518 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);
5519 if (!p->texture_camera)
5523 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5525 if (!p->texture_reflection)
5526 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);
5527 if (!p->texture_reflection)
5533 r_refdef.view = originalview;
5534 r_refdef.view.showdebug = false;
5535 r_refdef.view.width = r_waterstate.waterwidth;
5536 r_refdef.view.height = r_waterstate.waterheight;
5537 r_refdef.view.useclipplane = true;
5538 myview = r_refdef.view;
5539 r_waterstate.renderingscene = true;
5540 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5542 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5544 r_refdef.view = myview;
5545 if(r_water_scissormode.integer)
5548 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5549 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5552 // render reflected scene and copy into texture
5553 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5554 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5555 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5556 r_refdef.view.clipplane = p->plane;
5558 // reverse the cullface settings for this render
5559 r_refdef.view.cullface_front = GL_FRONT;
5560 r_refdef.view.cullface_back = GL_BACK;
5561 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5563 r_refdef.view.usecustompvs = true;
5565 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5567 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5570 R_ResetViewRendering3D();
5571 R_ClearScreen(r_refdef.fogenabled);
5572 if(r_water_scissormode.integer & 2)
5573 R_View_UpdateWithScissor(myscissor);
5576 if(r_water_scissormode.integer & 1)
5577 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5580 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);
5583 // render the normal view scene and copy into texture
5584 // (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)
5585 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5587 r_refdef.view = myview;
5588 if(r_water_scissormode.integer)
5591 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5592 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5595 r_waterstate.renderingrefraction = true;
5597 r_refdef.view.clipplane = p->plane;
5598 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5599 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5601 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5603 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5604 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5605 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5606 R_RenderView_UpdateViewVectors();
5607 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5609 r_refdef.view.usecustompvs = true;
5610 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
5614 PlaneClassify(&r_refdef.view.clipplane);
5616 R_ResetViewRendering3D();
5617 R_ClearScreen(r_refdef.fogenabled);
5618 if(r_water_scissormode.integer & 2)
5619 R_View_UpdateWithScissor(myscissor);
5622 if(r_water_scissormode.integer & 1)
5623 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5626 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);
5627 r_waterstate.renderingrefraction = false;
5629 else if (p->materialflags & MATERIALFLAG_CAMERA)
5631 r_refdef.view = myview;
5633 r_refdef.view.clipplane = p->plane;
5634 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5635 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5637 r_refdef.view.width = r_waterstate.camerawidth;
5638 r_refdef.view.height = r_waterstate.cameraheight;
5639 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5640 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5642 if(p->camera_entity)
5644 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5645 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5648 // note: all of the view is used for displaying... so
5649 // there is no use in scissoring
5651 // reverse the cullface settings for this render
5652 r_refdef.view.cullface_front = GL_FRONT;
5653 r_refdef.view.cullface_back = GL_BACK;
5654 // also reverse the view matrix
5655 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
5656 R_RenderView_UpdateViewVectors();
5657 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5659 r_refdef.view.usecustompvs = true;
5660 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);
5663 // camera needs no clipplane
5664 r_refdef.view.useclipplane = false;
5666 PlaneClassify(&r_refdef.view.clipplane);
5668 R_ResetViewRendering3D();
5669 R_ClearScreen(r_refdef.fogenabled);
5673 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);
5674 r_waterstate.renderingrefraction = false;
5678 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5679 r_waterstate.renderingscene = false;
5680 r_refdef.view = originalview;
5681 R_ResetViewRendering3D();
5682 R_ClearScreen(r_refdef.fogenabled);
5686 r_refdef.view = originalview;
5687 r_waterstate.renderingscene = false;
5688 Cvar_SetValueQuick(&r_water, 0);
5689 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5693 void R_Bloom_StartFrame(void)
5695 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5696 int viewwidth, viewheight;
5699 if (r_viewscale_fpsscaling.integer)
5701 double actualframetime;
5702 double targetframetime;
5704 actualframetime = r_refdef.lastdrawscreentime;
5705 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5706 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5707 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5708 if (r_viewscale_fpsscaling_stepsize.value > 0)
5709 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5710 viewscalefpsadjusted += adjust;
5711 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5714 viewscalefpsadjusted = 1.0f;
5716 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5718 switch(vid.renderpath)
5720 case RENDERPATH_GL20:
5721 case RENDERPATH_D3D9:
5722 case RENDERPATH_D3D10:
5723 case RENDERPATH_D3D11:
5724 case RENDERPATH_SOFT:
5725 case RENDERPATH_GLES2:
5727 case RENDERPATH_GL13:
5728 case RENDERPATH_GL11:
5732 // set bloomwidth and bloomheight to the bloom resolution that will be
5733 // used (often less than the screen resolution for faster rendering)
5734 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5735 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5736 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5737 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5738 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5740 // calculate desired texture sizes
5741 if (vid.support.arb_texture_non_power_of_two)
5743 screentexturewidth = vid.width;
5744 screentextureheight = vid.height;
5745 bloomtexturewidth = r_bloomstate.bloomwidth;
5746 bloomtextureheight = r_bloomstate.bloomheight;
5750 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
5751 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
5752 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
5753 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
5756 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))
5758 Cvar_SetValueQuick(&r_hdr, 0);
5759 Cvar_SetValueQuick(&r_bloom, 0);
5760 Cvar_SetValueQuick(&r_motionblur, 0);
5761 Cvar_SetValueQuick(&r_damageblur, 0);
5764 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)
5765 screentexturewidth = screentextureheight = 0;
5766 if (!r_hdr.integer && !r_bloom.integer)
5767 bloomtexturewidth = bloomtextureheight = 0;
5769 textype = TEXTYPE_COLORBUFFER;
5770 switch (vid.renderpath)
5772 case RENDERPATH_GL20:
5773 case RENDERPATH_GLES2:
5774 if (vid.support.ext_framebuffer_object)
5776 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5777 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5780 case RENDERPATH_D3D9:
5781 case RENDERPATH_D3D10:
5782 case RENDERPATH_D3D11:
5783 case RENDERPATH_SOFT:
5784 case RENDERPATH_GL13:
5785 case RENDERPATH_GL11:
5789 // allocate textures as needed
5790 if (r_bloomstate.screentexturewidth != screentexturewidth
5791 || r_bloomstate.screentextureheight != screentextureheight
5792 || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5793 || r_bloomstate.bloomtextureheight != bloomtextureheight
5794 || r_bloomstate.texturetype != textype
5795 || r_bloomstate.viewfbo != r_viewfbo.integer)
5797 if (r_bloomstate.texture_bloom)
5798 R_FreeTexture(r_bloomstate.texture_bloom);
5799 r_bloomstate.texture_bloom = NULL;
5800 if (r_bloomstate.texture_screen)
5801 R_FreeTexture(r_bloomstate.texture_screen);
5802 r_bloomstate.texture_screen = NULL;
5803 if (r_bloomstate.fbo_framebuffer)
5804 R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5805 r_bloomstate.fbo_framebuffer = 0;
5806 if (r_bloomstate.texture_framebuffercolor)
5807 R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5808 r_bloomstate.texture_framebuffercolor = NULL;
5809 if (r_bloomstate.texture_framebufferdepth)
5810 R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5811 r_bloomstate.texture_framebufferdepth = NULL;
5812 r_bloomstate.screentexturewidth = screentexturewidth;
5813 r_bloomstate.screentextureheight = screentextureheight;
5814 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5815 r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5816 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5818 // FIXME: choose depth bits based on a cvar
5819 r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5820 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);
5821 r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5822 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5823 // render depth into one texture and normalmap into the other
5827 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5828 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5829 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
5830 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
5831 Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
5834 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5835 r_bloomstate.bloomtextureheight = bloomtextureheight;
5836 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5837 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);
5838 r_bloomstate.viewfbo = r_viewfbo.integer;
5839 r_bloomstate.texturetype = textype;
5842 // when doing a reduced render (HDR) we want to use a smaller area
5843 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5844 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5845 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5846 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5847 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5849 // set up a texcoord array for the full resolution screen image
5850 // (we have to keep this around to copy back during final render)
5851 r_bloomstate.screentexcoord2f[0] = 0;
5852 r_bloomstate.screentexcoord2f[1] = (float)viewheight / (float)r_bloomstate.screentextureheight;
5853 r_bloomstate.screentexcoord2f[2] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
5854 r_bloomstate.screentexcoord2f[3] = (float)viewheight / (float)r_bloomstate.screentextureheight;
5855 r_bloomstate.screentexcoord2f[4] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
5856 r_bloomstate.screentexcoord2f[5] = 0;
5857 r_bloomstate.screentexcoord2f[6] = 0;
5858 r_bloomstate.screentexcoord2f[7] = 0;
5860 // set up a texcoord array for the reduced resolution bloom image
5861 // (which will be additive blended over the screen image)
5862 r_bloomstate.bloomtexcoord2f[0] = 0;
5863 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5864 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5865 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5866 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5867 r_bloomstate.bloomtexcoord2f[5] = 0;
5868 r_bloomstate.bloomtexcoord2f[6] = 0;
5869 r_bloomstate.bloomtexcoord2f[7] = 0;
5871 switch(vid.renderpath)
5873 case RENDERPATH_GL11:
5874 case RENDERPATH_GL13:
5875 case RENDERPATH_GL20:
5876 case RENDERPATH_SOFT:
5877 case RENDERPATH_GLES2:
5879 case RENDERPATH_D3D9:
5880 case RENDERPATH_D3D10:
5881 case RENDERPATH_D3D11:
5884 for (i = 0;i < 4;i++)
5886 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5887 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5888 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5889 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5895 if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
5897 r_bloomstate.enabled = true;
5898 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
5901 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);
5903 if (r_bloomstate.fbo_framebuffer)
5904 r_refdef.view.clear = true;
5907 void R_Bloom_CopyBloomTexture(float colorscale)
5909 r_refdef.stats.bloom++;
5911 // scale down screen texture to the bloom texture size
5913 R_Mesh_SetMainRenderTargets();
5914 R_SetViewport(&r_bloomstate.viewport);
5915 GL_BlendFunc(GL_ONE, GL_ZERO);
5916 GL_Color(colorscale, colorscale, colorscale, 1);
5917 // 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...
5918 switch(vid.renderpath)
5920 case RENDERPATH_GL11:
5921 case RENDERPATH_GL13:
5922 case RENDERPATH_GL20:
5923 case RENDERPATH_SOFT:
5924 case RENDERPATH_GLES2:
5925 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5927 case RENDERPATH_D3D9:
5928 case RENDERPATH_D3D10:
5929 case RENDERPATH_D3D11:
5930 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5933 // TODO: do boxfilter scale-down in shader?
5934 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5935 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5936 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5938 // we now have a bloom image in the framebuffer
5939 // copy it into the bloom image texture for later processing
5940 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);
5941 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5944 void R_Bloom_CopyHDRTexture(void)
5946 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);
5947 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5950 void R_Bloom_MakeTexture(void)
5953 float xoffset, yoffset, r, brighten;
5955 r_refdef.stats.bloom++;
5957 R_ResetViewRendering2D();
5959 // we have a bloom image in the framebuffer
5961 R_SetViewport(&r_bloomstate.viewport);
5963 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5966 r = bound(0, r_bloom_colorexponent.value / x, 1);
5967 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5969 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5970 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5971 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5972 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5974 // copy the vertically blurred bloom view to a texture
5975 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);
5976 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5979 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5980 brighten = r_bloom_brighten.value;
5981 if (r_bloomstate.hdr)
5982 brighten *= r_hdr_range.value;
5983 brighten = sqrt(brighten);
5985 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5986 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5988 for (dir = 0;dir < 2;dir++)
5990 // blend on at multiple vertical offsets to achieve a vertical blur
5991 // TODO: do offset blends using GLSL
5992 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5993 GL_BlendFunc(GL_ONE, GL_ZERO);
5994 for (x = -range;x <= range;x++)
5996 if (!dir){xoffset = 0;yoffset = x;}
5997 else {xoffset = x;yoffset = 0;}
5998 xoffset /= (float)r_bloomstate.bloomtexturewidth;
5999 yoffset /= (float)r_bloomstate.bloomtextureheight;
6000 // compute a texcoord array with the specified x and y offset
6001 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6002 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6003 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6004 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6005 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6006 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6007 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6008 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6009 // this r value looks like a 'dot' particle, fading sharply to
6010 // black at the edges
6011 // (probably not realistic but looks good enough)
6012 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6013 //r = brighten/(range*2+1);
6014 r = brighten / (range * 2 + 1);
6016 r *= (1 - x*x/(float)(range*range));
6017 GL_Color(r, r, r, 1);
6018 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6019 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6020 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6021 GL_BlendFunc(GL_ONE, GL_ONE);
6024 // copy the vertically blurred bloom view to a texture
6025 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);
6026 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6030 void R_HDR_RenderBloomTexture(void)
6032 int oldwidth, oldheight;
6033 float oldcolorscale;
6034 qboolean oldwaterstate;
6036 oldwaterstate = r_waterstate.enabled;
6037 oldcolorscale = r_refdef.view.colorscale;
6038 oldwidth = r_refdef.view.width;
6039 oldheight = r_refdef.view.height;
6040 r_refdef.view.width = r_bloomstate.bloomwidth;
6041 r_refdef.view.height = r_bloomstate.bloomheight;
6043 if(r_hdr.integer < 2)
6044 r_waterstate.enabled = false;
6046 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
6047 // TODO: add exposure compensation features
6048 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6050 r_refdef.view.showdebug = false;
6051 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6053 R_ResetViewRendering3D();
6055 R_ClearScreen(r_refdef.fogenabled);
6056 if (r_timereport_active)
6057 R_TimeReport("HDRclear");
6060 if (r_timereport_active)
6061 R_TimeReport("visibility");
6063 // only do secondary renders with HDR if r_hdr is 2 or higher
6064 r_waterstate.numwaterplanes = 0;
6065 if (r_waterstate.enabled)
6066 R_RenderWaterPlanes();
6068 r_refdef.view.showdebug = true;
6070 r_waterstate.numwaterplanes = 0;
6072 R_ResetViewRendering2D();
6074 R_Bloom_CopyHDRTexture();
6075 R_Bloom_MakeTexture();
6077 // restore the view settings
6078 r_waterstate.enabled = oldwaterstate;
6079 r_refdef.view.width = oldwidth;
6080 r_refdef.view.height = oldheight;
6081 r_refdef.view.colorscale = oldcolorscale;
6083 R_ResetViewRendering3D();
6085 R_ClearScreen(r_refdef.fogenabled);
6086 if (r_timereport_active)
6087 R_TimeReport("viewclear");
6090 static void R_BlendView(void)
6092 unsigned int permutation;
6093 float uservecs[4][4];
6095 switch (vid.renderpath)
6097 case RENDERPATH_GL20:
6098 case RENDERPATH_D3D9:
6099 case RENDERPATH_D3D10:
6100 case RENDERPATH_D3D11:
6101 case RENDERPATH_SOFT:
6102 case RENDERPATH_GLES2:
6104 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6105 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6106 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6107 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6108 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6110 if (r_bloomstate.texture_screen)
6112 // make sure the buffer is available
6113 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6115 R_ResetViewRendering2D();
6116 R_Mesh_SetMainRenderTargets();
6118 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6120 // declare variables
6122 static float avgspeed;
6124 speed = VectorLength(cl.movement_velocity);
6126 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6127 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6129 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6130 speed = bound(0, speed, 1);
6131 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6133 // calculate values into a standard alpha
6134 cl.motionbluralpha = 1 - exp(-
6136 (r_motionblur.value * speed / 80)
6138 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6141 max(0.0001, cl.time - cl.oldtime) // fps independent
6144 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6145 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6147 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6149 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6150 GL_Color(1, 1, 1, cl.motionbluralpha);
6151 switch(vid.renderpath)
6153 case RENDERPATH_GL11:
6154 case RENDERPATH_GL13:
6155 case RENDERPATH_GL20:
6156 case RENDERPATH_SOFT:
6157 case RENDERPATH_GLES2:
6158 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6160 case RENDERPATH_D3D9:
6161 case RENDERPATH_D3D10:
6162 case RENDERPATH_D3D11:
6163 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6166 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6167 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6168 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6172 // copy view into the screen texture
6173 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);
6174 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6176 else if (!r_bloomstate.texture_bloom)
6178 // we may still have to do view tint...
6179 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6181 // apply a color tint to the whole view
6182 R_ResetViewRendering2D();
6183 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6184 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6185 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6186 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6187 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6189 break; // no screen processing, no bloom, skip it
6192 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6194 // render simple bloom effect
6195 // copy the screen and shrink it and darken it for the bloom process
6196 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6197 // make the bloom texture
6198 R_Bloom_MakeTexture();
6201 #if _MSC_VER >= 1400
6202 #define sscanf sscanf_s
6204 memset(uservecs, 0, sizeof(uservecs));
6205 if (r_glsl_postprocess_uservec1_enable.integer)
6206 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6207 if (r_glsl_postprocess_uservec2_enable.integer)
6208 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6209 if (r_glsl_postprocess_uservec3_enable.integer)
6210 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6211 if (r_glsl_postprocess_uservec4_enable.integer)
6212 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6214 R_ResetViewRendering2D();
6215 GL_Color(1, 1, 1, 1);
6216 GL_BlendFunc(GL_ONE, GL_ZERO);
6218 switch(vid.renderpath)
6220 case RENDERPATH_GL20:
6221 case RENDERPATH_GLES2:
6222 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6223 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6224 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6225 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6226 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6227 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]);
6228 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6229 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]);
6230 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]);
6231 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]);
6232 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]);
6233 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6234 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6235 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);
6237 case RENDERPATH_D3D9:
6239 // 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...
6240 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6241 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6242 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6243 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6244 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6245 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6246 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6247 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6248 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6249 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6250 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6251 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6252 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6253 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6256 case RENDERPATH_D3D10:
6257 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6259 case RENDERPATH_D3D11:
6260 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6262 case RENDERPATH_SOFT:
6263 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6264 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6265 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6266 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6267 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6268 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6269 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6270 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6271 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6272 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6273 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6274 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6275 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6276 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6281 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6282 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6284 case RENDERPATH_GL13:
6285 case RENDERPATH_GL11:
6286 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6288 // apply a color tint to the whole view
6289 R_ResetViewRendering2D();
6290 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6291 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6292 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6293 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6294 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6300 matrix4x4_t r_waterscrollmatrix;
6302 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6304 if (r_refdef.fog_density)
6306 r_refdef.fogcolor[0] = r_refdef.fog_red;
6307 r_refdef.fogcolor[1] = r_refdef.fog_green;
6308 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6310 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6311 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6312 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6313 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6317 VectorCopy(r_refdef.fogcolor, fogvec);
6318 // color.rgb *= ContrastBoost * SceneBrightness;
6319 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6320 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6321 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6322 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6327 void R_UpdateVariables(void)
6331 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6333 r_refdef.farclip = r_farclip_base.value;
6334 if (r_refdef.scene.worldmodel)
6335 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6336 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6338 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6339 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6340 r_refdef.polygonfactor = 0;
6341 r_refdef.polygonoffset = 0;
6342 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6343 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6345 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6346 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6347 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6348 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6349 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6350 if (FAKELIGHT_ENABLED)
6352 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6354 if (r_showsurfaces.integer)
6356 r_refdef.scene.rtworld = false;
6357 r_refdef.scene.rtworldshadows = false;
6358 r_refdef.scene.rtdlight = false;
6359 r_refdef.scene.rtdlightshadows = false;
6360 r_refdef.lightmapintensity = 0;
6363 if (gamemode == GAME_NEHAHRA)
6365 if (gl_fogenable.integer)
6367 r_refdef.oldgl_fogenable = true;
6368 r_refdef.fog_density = gl_fogdensity.value;
6369 r_refdef.fog_red = gl_fogred.value;
6370 r_refdef.fog_green = gl_foggreen.value;
6371 r_refdef.fog_blue = gl_fogblue.value;
6372 r_refdef.fog_alpha = 1;
6373 r_refdef.fog_start = 0;
6374 r_refdef.fog_end = gl_skyclip.value;
6375 r_refdef.fog_height = 1<<30;
6376 r_refdef.fog_fadedepth = 128;
6378 else if (r_refdef.oldgl_fogenable)
6380 r_refdef.oldgl_fogenable = false;
6381 r_refdef.fog_density = 0;
6382 r_refdef.fog_red = 0;
6383 r_refdef.fog_green = 0;
6384 r_refdef.fog_blue = 0;
6385 r_refdef.fog_alpha = 0;
6386 r_refdef.fog_start = 0;
6387 r_refdef.fog_end = 0;
6388 r_refdef.fog_height = 1<<30;
6389 r_refdef.fog_fadedepth = 128;
6393 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6394 r_refdef.fog_start = max(0, r_refdef.fog_start);
6395 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6397 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6399 if (r_refdef.fog_density && r_drawfog.integer)
6401 r_refdef.fogenabled = true;
6402 // this is the point where the fog reaches 0.9986 alpha, which we
6403 // consider a good enough cutoff point for the texture
6404 // (0.9986 * 256 == 255.6)
6405 if (r_fog_exp2.integer)
6406 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6408 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6409 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6410 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6411 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6412 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6413 R_BuildFogHeightTexture();
6414 // fog color was already set
6415 // update the fog texture
6416 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)
6417 R_BuildFogTexture();
6418 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6419 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6422 r_refdef.fogenabled = false;
6424 switch(vid.renderpath)
6426 case RENDERPATH_GL20:
6427 case RENDERPATH_D3D9:
6428 case RENDERPATH_D3D10:
6429 case RENDERPATH_D3D11:
6430 case RENDERPATH_SOFT:
6431 case RENDERPATH_GLES2:
6432 if(v_glslgamma.integer && !vid_gammatables_trivial)
6434 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6436 // build GLSL gamma texture
6437 #define RAMPWIDTH 256
6438 unsigned short ramp[RAMPWIDTH * 3];
6439 unsigned char rampbgr[RAMPWIDTH][4];
6442 r_texture_gammaramps_serial = vid_gammatables_serial;
6444 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6445 for(i = 0; i < RAMPWIDTH; ++i)
6447 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6448 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6449 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6452 if (r_texture_gammaramps)
6454 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6458 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6464 // remove GLSL gamma texture
6467 case RENDERPATH_GL13:
6468 case RENDERPATH_GL11:
6473 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6474 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6480 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6481 if( scenetype != r_currentscenetype ) {
6482 // store the old scenetype
6483 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6484 r_currentscenetype = scenetype;
6485 // move in the new scene
6486 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6495 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6497 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6498 if( scenetype == r_currentscenetype ) {
6499 return &r_refdef.scene;
6501 return &r_scenes_store[ scenetype ];
6510 int dpsoftrast_test;
6511 void R_RenderView(void)
6513 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6515 dpsoftrast_test = r_test.integer;
6517 if (r_timereport_active)
6518 R_TimeReport("start");
6519 r_textureframe++; // used only by R_GetCurrentTexture
6520 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6522 if(R_CompileShader_CheckStaticParms())
6525 if (!r_drawentities.integer)
6526 r_refdef.scene.numentities = 0;
6528 R_AnimCache_ClearCache();
6529 R_FrameData_NewFrame();
6531 /* adjust for stereo display */
6532 if(R_Stereo_Active())
6534 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);
6535 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6538 if (r_refdef.view.isoverlay)
6540 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6541 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6542 R_TimeReport("depthclear");
6544 r_refdef.view.showdebug = false;
6546 r_waterstate.enabled = false;
6547 r_waterstate.numwaterplanes = 0;
6551 r_refdef.view.matrix = originalmatrix;
6557 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6559 r_refdef.view.matrix = originalmatrix;
6560 return; //Host_Error ("R_RenderView: NULL worldmodel");
6563 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6565 R_RenderView_UpdateViewVectors();
6567 R_Shadow_UpdateWorldLightSelection();
6569 R_Bloom_StartFrame();
6570 R_Water_StartFrame();
6573 if (r_timereport_active)
6574 R_TimeReport("viewsetup");
6576 R_ResetViewRendering3D();
6578 if (r_refdef.view.clear || r_refdef.fogenabled)
6580 R_ClearScreen(r_refdef.fogenabled);
6581 if (r_timereport_active)
6582 R_TimeReport("viewclear");
6584 r_refdef.view.clear = true;
6586 // this produces a bloom texture to be used in R_BlendView() later
6587 if (r_bloomstate.hdr)
6589 R_HDR_RenderBloomTexture();
6590 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6591 r_textureframe++; // used only by R_GetCurrentTexture
6594 r_refdef.view.showdebug = true;
6597 if (r_timereport_active)
6598 R_TimeReport("visibility");
6600 r_waterstate.numwaterplanes = 0;
6601 if (r_waterstate.enabled)
6602 R_RenderWaterPlanes();
6605 r_waterstate.numwaterplanes = 0;
6608 if (r_timereport_active)
6609 R_TimeReport("blendview");
6611 GL_Scissor(0, 0, vid.width, vid.height);
6612 GL_ScissorTest(false);
6614 r_refdef.view.matrix = originalmatrix;
6619 void R_RenderWaterPlanes(void)
6621 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6623 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6624 if (r_timereport_active)
6625 R_TimeReport("waterworld");
6628 // don't let sound skip if going slow
6629 if (r_refdef.scene.extraupdate)
6632 R_DrawModelsAddWaterPlanes();
6633 if (r_timereport_active)
6634 R_TimeReport("watermodels");
6636 if (r_waterstate.numwaterplanes)
6638 R_Water_ProcessPlanes();
6639 if (r_timereport_active)
6640 R_TimeReport("waterscenes");
6644 extern void R_DrawLightningBeams (void);
6645 extern void VM_CL_AddPolygonsToMeshQueue (void);
6646 extern void R_DrawPortals (void);
6647 extern cvar_t cl_locs_show;
6648 static void R_DrawLocs(void);
6649 static void R_DrawEntityBBoxes(void);
6650 static void R_DrawModelDecals(void);
6651 extern void R_DrawModelShadows(void);
6652 extern void R_DrawModelShadowMaps(void);
6653 extern cvar_t cl_decals_newsystem;
6654 extern qboolean r_shadow_usingdeferredprepass;
6655 void R_RenderScene(void)
6657 qboolean shadowmapping = false;
6659 if (r_timereport_active)
6660 R_TimeReport("beginscene");
6662 r_refdef.stats.renders++;
6666 // don't let sound skip if going slow
6667 if (r_refdef.scene.extraupdate)
6670 R_MeshQueue_BeginScene();
6674 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);
6676 if (r_timereport_active)
6677 R_TimeReport("skystartframe");
6679 if (cl.csqc_vidvars.drawworld)
6681 // don't let sound skip if going slow
6682 if (r_refdef.scene.extraupdate)
6685 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6687 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6688 if (r_timereport_active)
6689 R_TimeReport("worldsky");
6692 if (R_DrawBrushModelsSky() && r_timereport_active)
6693 R_TimeReport("bmodelsky");
6695 if (skyrendermasked && skyrenderlater)
6697 // we have to force off the water clipping plane while rendering sky
6701 if (r_timereport_active)
6702 R_TimeReport("sky");
6706 R_AnimCache_CacheVisibleEntities();
6707 if (r_timereport_active)
6708 R_TimeReport("animation");
6710 R_Shadow_PrepareLights();
6711 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6712 R_Shadow_PrepareModelShadows();
6713 if (r_timereport_active)
6714 R_TimeReport("preparelights");
6716 if (R_Shadow_ShadowMappingEnabled())
6717 shadowmapping = true;
6719 if (r_shadow_usingdeferredprepass)
6720 R_Shadow_DrawPrepass();
6722 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6724 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6725 if (r_timereport_active)
6726 R_TimeReport("worlddepth");
6728 if (r_depthfirst.integer >= 2)
6730 R_DrawModelsDepth();
6731 if (r_timereport_active)
6732 R_TimeReport("modeldepth");
6735 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6737 R_DrawModelShadowMaps();
6738 R_ResetViewRendering3D();
6739 // don't let sound skip if going slow
6740 if (r_refdef.scene.extraupdate)
6744 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6746 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6747 if (r_timereport_active)
6748 R_TimeReport("world");
6751 // don't let sound skip if going slow
6752 if (r_refdef.scene.extraupdate)
6756 if (r_timereport_active)
6757 R_TimeReport("models");
6759 // don't let sound skip if going slow
6760 if (r_refdef.scene.extraupdate)
6763 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6765 R_DrawModelShadows();
6766 R_ResetViewRendering3D();
6767 // don't let sound skip if going slow
6768 if (r_refdef.scene.extraupdate)
6772 if (!r_shadow_usingdeferredprepass)
6774 R_Shadow_DrawLights();
6775 if (r_timereport_active)
6776 R_TimeReport("rtlights");
6779 // don't let sound skip if going slow
6780 if (r_refdef.scene.extraupdate)
6783 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6785 R_DrawModelShadows();
6786 R_ResetViewRendering3D();
6787 // don't let sound skip if going slow
6788 if (r_refdef.scene.extraupdate)
6792 if (cl.csqc_vidvars.drawworld)
6794 if (cl_decals_newsystem.integer)
6796 R_DrawModelDecals();
6797 if (r_timereport_active)
6798 R_TimeReport("modeldecals");
6803 if (r_timereport_active)
6804 R_TimeReport("decals");
6808 if (r_timereport_active)
6809 R_TimeReport("particles");
6812 if (r_timereport_active)
6813 R_TimeReport("explosions");
6815 R_DrawLightningBeams();
6816 if (r_timereport_active)
6817 R_TimeReport("lightning");
6820 VM_CL_AddPolygonsToMeshQueue();
6822 if (r_refdef.view.showdebug)
6824 if (cl_locs_show.integer)
6827 if (r_timereport_active)
6828 R_TimeReport("showlocs");
6831 if (r_drawportals.integer)
6834 if (r_timereport_active)
6835 R_TimeReport("portals");
6838 if (r_showbboxes.value > 0)
6840 R_DrawEntityBBoxes();
6841 if (r_timereport_active)
6842 R_TimeReport("bboxes");
6846 R_MeshQueue_RenderTransparent();
6847 if (r_timereport_active)
6848 R_TimeReport("drawtrans");
6850 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))
6852 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6853 if (r_timereport_active)
6854 R_TimeReport("worlddebug");
6855 R_DrawModelsDebug();
6856 if (r_timereport_active)
6857 R_TimeReport("modeldebug");
6860 if (cl.csqc_vidvars.drawworld)
6862 R_Shadow_DrawCoronas();
6863 if (r_timereport_active)
6864 R_TimeReport("coronas");
6869 GL_DepthTest(false);
6870 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6871 GL_Color(1, 1, 1, 1);
6872 qglBegin(GL_POLYGON);
6873 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6874 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6875 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6876 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6878 qglBegin(GL_POLYGON);
6879 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]);
6880 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]);
6881 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]);
6882 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]);
6884 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6888 // don't let sound skip if going slow
6889 if (r_refdef.scene.extraupdate)
6892 R_ResetViewRendering2D();
6895 static const unsigned short bboxelements[36] =
6905 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6908 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6910 RSurf_ActiveWorldEntity();
6912 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6913 GL_DepthMask(false);
6914 GL_DepthRange(0, 1);
6915 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6916 // R_Mesh_ResetTextureState();
6918 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6919 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6920 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6921 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6922 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6923 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6924 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6925 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6926 R_FillColors(color4f, 8, cr, cg, cb, ca);
6927 if (r_refdef.fogenabled)
6929 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6931 f1 = RSurf_FogVertex(v);
6933 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6934 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6935 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6938 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6939 R_Mesh_ResetTextureState();
6940 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6941 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6944 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6948 prvm_edict_t *edict;
6949 prvm_prog_t *prog_save = prog;
6951 // this function draws bounding boxes of server entities
6955 GL_CullFace(GL_NONE);
6956 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6960 for (i = 0;i < numsurfaces;i++)
6962 edict = PRVM_EDICT_NUM(surfacelist[i]);
6963 switch ((int)edict->fields.server->solid)
6965 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
6966 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
6967 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
6968 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6969 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
6970 default: Vector4Set(color, 0, 0, 0, 0.50);break;
6972 color[3] *= r_showbboxes.value;
6973 color[3] = bound(0, color[3], 1);
6974 GL_DepthTest(!r_showdisabledepthtest.integer);
6975 GL_CullFace(r_refdef.view.cullface_front);
6976 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6982 static void R_DrawEntityBBoxes(void)
6985 prvm_edict_t *edict;
6987 prvm_prog_t *prog_save = prog;
6989 // this function draws bounding boxes of server entities
6995 for (i = 0;i < prog->num_edicts;i++)
6997 edict = PRVM_EDICT_NUM(i);
6998 if (edict->priv.server->free)
7000 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7001 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
7003 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
7005 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7006 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7012 static const int nomodelelement3i[24] =
7024 static const unsigned short nomodelelement3s[24] =
7036 static const float nomodelvertex3f[6*3] =
7046 static const float nomodelcolor4f[6*4] =
7048 0.0f, 0.0f, 0.5f, 1.0f,
7049 0.0f, 0.0f, 0.5f, 1.0f,
7050 0.0f, 0.5f, 0.0f, 1.0f,
7051 0.0f, 0.5f, 0.0f, 1.0f,
7052 0.5f, 0.0f, 0.0f, 1.0f,
7053 0.5f, 0.0f, 0.0f, 1.0f
7056 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7062 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);
7064 // this is only called once per entity so numsurfaces is always 1, and
7065 // surfacelist is always {0}, so this code does not handle batches
7067 if (rsurface.ent_flags & RENDER_ADDITIVE)
7069 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7070 GL_DepthMask(false);
7072 else if (rsurface.colormod[3] < 1)
7074 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7075 GL_DepthMask(false);
7079 GL_BlendFunc(GL_ONE, GL_ZERO);
7082 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7083 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7084 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7085 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7086 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7087 for (i = 0, c = color4f;i < 6;i++, c += 4)
7089 c[0] *= rsurface.colormod[0];
7090 c[1] *= rsurface.colormod[1];
7091 c[2] *= rsurface.colormod[2];
7092 c[3] *= rsurface.colormod[3];
7094 if (r_refdef.fogenabled)
7096 for (i = 0, c = color4f;i < 6;i++, c += 4)
7098 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7100 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7101 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7102 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7105 // R_Mesh_ResetTextureState();
7106 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7107 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7108 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7111 void R_DrawNoModel(entity_render_t *ent)
7114 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7115 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7116 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7118 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7121 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7123 vec3_t right1, right2, diff, normal;
7125 VectorSubtract (org2, org1, normal);
7127 // calculate 'right' vector for start
7128 VectorSubtract (r_refdef.view.origin, org1, diff);
7129 CrossProduct (normal, diff, right1);
7130 VectorNormalize (right1);
7132 // calculate 'right' vector for end
7133 VectorSubtract (r_refdef.view.origin, org2, diff);
7134 CrossProduct (normal, diff, right2);
7135 VectorNormalize (right2);
7137 vert[ 0] = org1[0] + width * right1[0];
7138 vert[ 1] = org1[1] + width * right1[1];
7139 vert[ 2] = org1[2] + width * right1[2];
7140 vert[ 3] = org1[0] - width * right1[0];
7141 vert[ 4] = org1[1] - width * right1[1];
7142 vert[ 5] = org1[2] - width * right1[2];
7143 vert[ 6] = org2[0] - width * right2[0];
7144 vert[ 7] = org2[1] - width * right2[1];
7145 vert[ 8] = org2[2] - width * right2[2];
7146 vert[ 9] = org2[0] + width * right2[0];
7147 vert[10] = org2[1] + width * right2[1];
7148 vert[11] = org2[2] + width * right2[2];
7151 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)
7153 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7154 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7155 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7156 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7157 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7158 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7159 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7160 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7161 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7162 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7163 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7164 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7167 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7172 VectorSet(v, x, y, z);
7173 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7174 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7176 if (i == mesh->numvertices)
7178 if (mesh->numvertices < mesh->maxvertices)
7180 VectorCopy(v, vertex3f);
7181 mesh->numvertices++;
7183 return mesh->numvertices;
7189 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7193 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7194 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7195 e = mesh->element3i + mesh->numtriangles * 3;
7196 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7198 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7199 if (mesh->numtriangles < mesh->maxtriangles)
7204 mesh->numtriangles++;
7206 element[1] = element[2];
7210 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7214 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7215 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7216 e = mesh->element3i + mesh->numtriangles * 3;
7217 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7219 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7220 if (mesh->numtriangles < mesh->maxtriangles)
7225 mesh->numtriangles++;
7227 element[1] = element[2];
7231 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7232 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7234 int planenum, planenum2;
7237 mplane_t *plane, *plane2;
7239 double temppoints[2][256*3];
7240 // figure out how large a bounding box we need to properly compute this brush
7242 for (w = 0;w < numplanes;w++)
7243 maxdist = max(maxdist, fabs(planes[w].dist));
7244 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7245 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7246 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7250 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7251 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7253 if (planenum2 == planenum)
7255 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);
7258 if (tempnumpoints < 3)
7260 // generate elements forming a triangle fan for this polygon
7261 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7265 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)
7267 texturelayer_t *layer;
7268 layer = t->currentlayers + t->currentnumlayers++;
7270 layer->depthmask = depthmask;
7271 layer->blendfunc1 = blendfunc1;
7272 layer->blendfunc2 = blendfunc2;
7273 layer->texture = texture;
7274 layer->texmatrix = *matrix;
7275 layer->color[0] = r;
7276 layer->color[1] = g;
7277 layer->color[2] = b;
7278 layer->color[3] = a;
7281 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7283 if(parms[0] == 0 && parms[1] == 0)
7285 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7286 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7291 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7294 index = parms[2] + r_refdef.scene.time * parms[3];
7295 index -= floor(index);
7296 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7299 case Q3WAVEFUNC_NONE:
7300 case Q3WAVEFUNC_NOISE:
7301 case Q3WAVEFUNC_COUNT:
7304 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7305 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7306 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7307 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7308 case Q3WAVEFUNC_TRIANGLE:
7310 f = index - floor(index);
7321 f = parms[0] + parms[1] * f;
7322 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7323 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7327 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7332 matrix4x4_t matrix, temp;
7333 switch(tcmod->tcmod)
7337 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7338 matrix = r_waterscrollmatrix;
7340 matrix = identitymatrix;
7342 case Q3TCMOD_ENTITYTRANSLATE:
7343 // this is used in Q3 to allow the gamecode to control texcoord
7344 // scrolling on the entity, which is not supported in darkplaces yet.
7345 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7347 case Q3TCMOD_ROTATE:
7348 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7349 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7350 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7353 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7355 case Q3TCMOD_SCROLL:
7356 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7358 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7359 w = (int) tcmod->parms[0];
7360 h = (int) tcmod->parms[1];
7361 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7363 idx = (int) floor(f * w * h);
7364 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7366 case Q3TCMOD_STRETCH:
7367 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7368 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7370 case Q3TCMOD_TRANSFORM:
7371 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7372 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7373 VectorSet(tcmat + 6, 0 , 0 , 1);
7374 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7375 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7377 case Q3TCMOD_TURBULENT:
7378 // this is handled in the RSurf_PrepareVertices function
7379 matrix = identitymatrix;
7383 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7386 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7388 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7389 char name[MAX_QPATH];
7390 skinframe_t *skinframe;
7391 unsigned char pixels[296*194];
7392 strlcpy(cache->name, skinname, sizeof(cache->name));
7393 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7394 if (developer_loading.integer)
7395 Con_Printf("loading %s\n", name);
7396 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7397 if (!skinframe || !skinframe->base)
7400 fs_offset_t filesize;
7402 f = FS_LoadFile(name, tempmempool, true, &filesize);
7405 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7406 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7410 cache->skinframe = skinframe;
7413 texture_t *R_GetCurrentTexture(texture_t *t)
7416 const entity_render_t *ent = rsurface.entity;
7417 dp_model_t *model = ent->model;
7418 q3shaderinfo_layer_tcmod_t *tcmod;
7420 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7421 return t->currentframe;
7422 t->update_lastrenderframe = r_textureframe;
7423 t->update_lastrenderentity = (void *)ent;
7425 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7426 t->camera_entity = ent->entitynumber;
7428 t->camera_entity = 0;
7430 // switch to an alternate material if this is a q1bsp animated material
7432 texture_t *texture = t;
7433 int s = rsurface.ent_skinnum;
7434 if ((unsigned int)s >= (unsigned int)model->numskins)
7436 if (model->skinscenes)
7438 if (model->skinscenes[s].framecount > 1)
7439 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7441 s = model->skinscenes[s].firstframe;
7444 t = t + s * model->num_surfaces;
7447 // use an alternate animation if the entity's frame is not 0,
7448 // and only if the texture has an alternate animation
7449 if (rsurface.ent_alttextures && t->anim_total[1])
7450 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7452 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7454 texture->currentframe = t;
7457 // update currentskinframe to be a qw skin or animation frame
7458 if (rsurface.ent_qwskin >= 0)
7460 i = rsurface.ent_qwskin;
7461 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7463 r_qwskincache_size = cl.maxclients;
7465 Mem_Free(r_qwskincache);
7466 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7468 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7469 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7470 t->currentskinframe = r_qwskincache[i].skinframe;
7471 if (t->currentskinframe == NULL)
7472 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7474 else if (t->numskinframes >= 2)
7475 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7476 if (t->backgroundnumskinframes >= 2)
7477 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7479 t->currentmaterialflags = t->basematerialflags;
7480 t->currentalpha = rsurface.colormod[3];
7481 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7482 t->currentalpha *= r_wateralpha.value;
7483 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7484 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7485 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7486 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7487 if (!(rsurface.ent_flags & RENDER_LIGHT))
7488 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7489 else if (FAKELIGHT_ENABLED)
7491 // no modellight if using fakelight for the map
7493 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7495 // pick a model lighting mode
7496 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7497 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7499 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7501 if (rsurface.ent_flags & RENDER_ADDITIVE)
7502 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7503 else if (t->currentalpha < 1)
7504 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7505 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7506 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7507 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7508 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7509 if (t->backgroundnumskinframes)
7510 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7511 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7513 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7514 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7517 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7518 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7519 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7521 // there is no tcmod
7522 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7524 t->currenttexmatrix = r_waterscrollmatrix;
7525 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7527 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7529 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7530 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7533 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7534 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7535 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7536 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7538 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7539 if (t->currentskinframe->qpixels)
7540 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7541 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7542 if (!t->basetexture)
7543 t->basetexture = r_texture_notexture;
7544 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7545 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7546 t->nmaptexture = t->currentskinframe->nmap;
7547 if (!t->nmaptexture)
7548 t->nmaptexture = r_texture_blanknormalmap;
7549 t->glosstexture = r_texture_black;
7550 t->glowtexture = t->currentskinframe->glow;
7551 t->fogtexture = t->currentskinframe->fog;
7552 t->reflectmasktexture = t->currentskinframe->reflect;
7553 if (t->backgroundnumskinframes)
7555 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7556 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7557 t->backgroundglosstexture = r_texture_black;
7558 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7559 if (!t->backgroundnmaptexture)
7560 t->backgroundnmaptexture = r_texture_blanknormalmap;
7564 t->backgroundbasetexture = r_texture_white;
7565 t->backgroundnmaptexture = r_texture_blanknormalmap;
7566 t->backgroundglosstexture = r_texture_black;
7567 t->backgroundglowtexture = NULL;
7569 t->specularpower = r_shadow_glossexponent.value;
7570 // TODO: store reference values for these in the texture?
7571 t->specularscale = 0;
7572 if (r_shadow_gloss.integer > 0)
7574 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7576 if (r_shadow_glossintensity.value > 0)
7578 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7579 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7580 t->specularscale = r_shadow_glossintensity.value;
7583 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7585 t->glosstexture = r_texture_white;
7586 t->backgroundglosstexture = r_texture_white;
7587 t->specularscale = r_shadow_gloss2intensity.value;
7588 t->specularpower = r_shadow_gloss2exponent.value;
7591 t->specularscale *= t->specularscalemod;
7592 t->specularpower *= t->specularpowermod;
7594 // lightmaps mode looks bad with dlights using actual texturing, so turn
7595 // off the colormap and glossmap, but leave the normalmap on as it still
7596 // accurately represents the shading involved
7597 if (gl_lightmaps.integer)
7599 t->basetexture = r_texture_grey128;
7600 t->pantstexture = r_texture_black;
7601 t->shirttexture = r_texture_black;
7602 t->nmaptexture = r_texture_blanknormalmap;
7603 t->glosstexture = r_texture_black;
7604 t->glowtexture = NULL;
7605 t->fogtexture = NULL;
7606 t->reflectmasktexture = NULL;
7607 t->backgroundbasetexture = NULL;
7608 t->backgroundnmaptexture = r_texture_blanknormalmap;
7609 t->backgroundglosstexture = r_texture_black;
7610 t->backgroundglowtexture = NULL;
7611 t->specularscale = 0;
7612 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7615 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7616 VectorClear(t->dlightcolor);
7617 t->currentnumlayers = 0;
7618 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7620 int blendfunc1, blendfunc2;
7622 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7624 blendfunc1 = GL_SRC_ALPHA;
7625 blendfunc2 = GL_ONE;
7627 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7629 blendfunc1 = GL_SRC_ALPHA;
7630 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7632 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7634 blendfunc1 = t->customblendfunc[0];
7635 blendfunc2 = t->customblendfunc[1];
7639 blendfunc1 = GL_ONE;
7640 blendfunc2 = GL_ZERO;
7642 // don't colormod evilblend textures
7643 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7644 VectorSet(t->lightmapcolor, 1, 1, 1);
7645 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7646 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7648 // fullbright is not affected by r_refdef.lightmapintensity
7649 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]);
7650 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7651 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]);
7652 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7653 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]);
7657 vec3_t ambientcolor;
7659 // set the color tint used for lights affecting this surface
7660 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7662 // q3bsp has no lightmap updates, so the lightstylevalue that
7663 // would normally be baked into the lightmap must be
7664 // applied to the color
7665 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7666 if (model->type == mod_brushq3)
7667 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7668 colorscale *= r_refdef.lightmapintensity;
7669 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7670 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7671 // basic lit geometry
7672 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]);
7673 // add pants/shirt if needed
7674 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7675 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]);
7676 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7677 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]);
7678 // now add ambient passes if needed
7679 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7681 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]);
7682 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7683 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]);
7684 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7685 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]);
7688 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7689 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]);
7690 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7692 // if this is opaque use alpha blend which will darken the earlier
7695 // if this is an alpha blended material, all the earlier passes
7696 // were darkened by fog already, so we only need to add the fog
7697 // color ontop through the fog mask texture
7699 // if this is an additive blended material, all the earlier passes
7700 // were darkened by fog already, and we should not add fog color
7701 // (because the background was not darkened, there is no fog color
7702 // that was lost behind it).
7703 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]);
7707 return t->currentframe;
7710 rsurfacestate_t rsurface;
7712 void RSurf_ActiveWorldEntity(void)
7714 dp_model_t *model = r_refdef.scene.worldmodel;
7715 //if (rsurface.entity == r_refdef.scene.worldentity)
7717 rsurface.entity = r_refdef.scene.worldentity;
7718 rsurface.skeleton = NULL;
7719 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7720 rsurface.ent_skinnum = 0;
7721 rsurface.ent_qwskin = -1;
7722 rsurface.ent_shadertime = 0;
7723 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7724 rsurface.matrix = identitymatrix;
7725 rsurface.inversematrix = identitymatrix;
7726 rsurface.matrixscale = 1;
7727 rsurface.inversematrixscale = 1;
7728 R_EntityMatrix(&identitymatrix);
7729 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7730 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7731 rsurface.fograngerecip = r_refdef.fograngerecip;
7732 rsurface.fogheightfade = r_refdef.fogheightfade;
7733 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7734 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7735 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7736 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7737 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7738 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7739 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7740 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7741 rsurface.colormod[3] = 1;
7742 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);
7743 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7744 rsurface.frameblend[0].lerp = 1;
7745 rsurface.ent_alttextures = false;
7746 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7747 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7748 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7749 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7750 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7751 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7752 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7753 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7754 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7755 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7756 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7757 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7758 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7759 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7760 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7761 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7762 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7763 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7764 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7765 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7766 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7767 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7768 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7769 rsurface.modelelement3i = model->surfmesh.data_element3i;
7770 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7771 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7772 rsurface.modelelement3s = model->surfmesh.data_element3s;
7773 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7774 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7775 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7776 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7777 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7778 rsurface.modelsurfaces = model->data_surfaces;
7779 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7780 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7781 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7782 rsurface.modelgeneratedvertex = false;
7783 rsurface.batchgeneratedvertex = false;
7784 rsurface.batchfirstvertex = 0;
7785 rsurface.batchnumvertices = 0;
7786 rsurface.batchfirsttriangle = 0;
7787 rsurface.batchnumtriangles = 0;
7788 rsurface.batchvertex3f = NULL;
7789 rsurface.batchvertex3f_vertexbuffer = NULL;
7790 rsurface.batchvertex3f_bufferoffset = 0;
7791 rsurface.batchsvector3f = NULL;
7792 rsurface.batchsvector3f_vertexbuffer = NULL;
7793 rsurface.batchsvector3f_bufferoffset = 0;
7794 rsurface.batchtvector3f = NULL;
7795 rsurface.batchtvector3f_vertexbuffer = NULL;
7796 rsurface.batchtvector3f_bufferoffset = 0;
7797 rsurface.batchnormal3f = NULL;
7798 rsurface.batchnormal3f_vertexbuffer = NULL;
7799 rsurface.batchnormal3f_bufferoffset = 0;
7800 rsurface.batchlightmapcolor4f = NULL;
7801 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7802 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7803 rsurface.batchtexcoordtexture2f = NULL;
7804 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7805 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7806 rsurface.batchtexcoordlightmap2f = NULL;
7807 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7808 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7809 rsurface.batchvertexmesh = NULL;
7810 rsurface.batchvertexmeshbuffer = NULL;
7811 rsurface.batchvertex3fbuffer = NULL;
7812 rsurface.batchelement3i = NULL;
7813 rsurface.batchelement3i_indexbuffer = NULL;
7814 rsurface.batchelement3i_bufferoffset = 0;
7815 rsurface.batchelement3s = NULL;
7816 rsurface.batchelement3s_indexbuffer = NULL;
7817 rsurface.batchelement3s_bufferoffset = 0;
7818 rsurface.passcolor4f = NULL;
7819 rsurface.passcolor4f_vertexbuffer = NULL;
7820 rsurface.passcolor4f_bufferoffset = 0;
7823 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7825 dp_model_t *model = ent->model;
7826 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7828 rsurface.entity = (entity_render_t *)ent;
7829 rsurface.skeleton = ent->skeleton;
7830 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7831 rsurface.ent_skinnum = ent->skinnum;
7832 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;
7833 rsurface.ent_shadertime = ent->shadertime;
7834 rsurface.ent_flags = ent->flags;
7835 rsurface.matrix = ent->matrix;
7836 rsurface.inversematrix = ent->inversematrix;
7837 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7838 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7839 R_EntityMatrix(&rsurface.matrix);
7840 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7841 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7842 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7843 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7844 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7845 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7846 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7847 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7848 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7849 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7850 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7851 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7852 rsurface.colormod[3] = ent->alpha;
7853 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7854 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7855 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7856 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7857 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7858 if (ent->model->brush.submodel && !prepass)
7860 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7861 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7863 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7865 if (ent->animcache_vertex3f)
7867 rsurface.modelvertex3f = ent->animcache_vertex3f;
7868 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7869 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7870 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7871 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7872 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7873 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7875 else if (wanttangents)
7877 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7878 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7879 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7880 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7881 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7882 rsurface.modelvertexmesh = NULL;
7883 rsurface.modelvertexmeshbuffer = NULL;
7884 rsurface.modelvertex3fbuffer = NULL;
7886 else if (wantnormals)
7888 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7889 rsurface.modelsvector3f = NULL;
7890 rsurface.modeltvector3f = NULL;
7891 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7892 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7893 rsurface.modelvertexmesh = NULL;
7894 rsurface.modelvertexmeshbuffer = NULL;
7895 rsurface.modelvertex3fbuffer = NULL;
7899 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7900 rsurface.modelsvector3f = NULL;
7901 rsurface.modeltvector3f = NULL;
7902 rsurface.modelnormal3f = NULL;
7903 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7904 rsurface.modelvertexmesh = NULL;
7905 rsurface.modelvertexmeshbuffer = NULL;
7906 rsurface.modelvertex3fbuffer = NULL;
7908 rsurface.modelvertex3f_vertexbuffer = 0;
7909 rsurface.modelvertex3f_bufferoffset = 0;
7910 rsurface.modelsvector3f_vertexbuffer = 0;
7911 rsurface.modelsvector3f_bufferoffset = 0;
7912 rsurface.modeltvector3f_vertexbuffer = 0;
7913 rsurface.modeltvector3f_bufferoffset = 0;
7914 rsurface.modelnormal3f_vertexbuffer = 0;
7915 rsurface.modelnormal3f_bufferoffset = 0;
7916 rsurface.modelgeneratedvertex = true;
7920 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7921 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7922 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7923 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7924 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7925 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7926 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7927 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7928 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7929 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7930 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7931 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7932 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7933 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7934 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7935 rsurface.modelgeneratedvertex = false;
7937 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7938 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7939 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7940 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7941 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7942 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7943 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7944 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7945 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7946 rsurface.modelelement3i = model->surfmesh.data_element3i;
7947 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7948 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7949 rsurface.modelelement3s = model->surfmesh.data_element3s;
7950 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7951 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7952 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7953 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7954 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7955 rsurface.modelsurfaces = model->data_surfaces;
7956 rsurface.batchgeneratedvertex = false;
7957 rsurface.batchfirstvertex = 0;
7958 rsurface.batchnumvertices = 0;
7959 rsurface.batchfirsttriangle = 0;
7960 rsurface.batchnumtriangles = 0;
7961 rsurface.batchvertex3f = NULL;
7962 rsurface.batchvertex3f_vertexbuffer = NULL;
7963 rsurface.batchvertex3f_bufferoffset = 0;
7964 rsurface.batchsvector3f = NULL;
7965 rsurface.batchsvector3f_vertexbuffer = NULL;
7966 rsurface.batchsvector3f_bufferoffset = 0;
7967 rsurface.batchtvector3f = NULL;
7968 rsurface.batchtvector3f_vertexbuffer = NULL;
7969 rsurface.batchtvector3f_bufferoffset = 0;
7970 rsurface.batchnormal3f = NULL;
7971 rsurface.batchnormal3f_vertexbuffer = NULL;
7972 rsurface.batchnormal3f_bufferoffset = 0;
7973 rsurface.batchlightmapcolor4f = NULL;
7974 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7975 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7976 rsurface.batchtexcoordtexture2f = NULL;
7977 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7978 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7979 rsurface.batchtexcoordlightmap2f = NULL;
7980 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7981 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7982 rsurface.batchvertexmesh = NULL;
7983 rsurface.batchvertexmeshbuffer = NULL;
7984 rsurface.batchvertex3fbuffer = NULL;
7985 rsurface.batchelement3i = NULL;
7986 rsurface.batchelement3i_indexbuffer = NULL;
7987 rsurface.batchelement3i_bufferoffset = 0;
7988 rsurface.batchelement3s = NULL;
7989 rsurface.batchelement3s_indexbuffer = NULL;
7990 rsurface.batchelement3s_bufferoffset = 0;
7991 rsurface.passcolor4f = NULL;
7992 rsurface.passcolor4f_vertexbuffer = NULL;
7993 rsurface.passcolor4f_bufferoffset = 0;
7996 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)
7998 rsurface.entity = r_refdef.scene.worldentity;
7999 rsurface.skeleton = NULL;
8000 rsurface.ent_skinnum = 0;
8001 rsurface.ent_qwskin = -1;
8002 rsurface.ent_shadertime = shadertime;
8003 rsurface.ent_flags = entflags;
8004 rsurface.modelnumvertices = numvertices;
8005 rsurface.modelnumtriangles = numtriangles;
8006 rsurface.matrix = *matrix;
8007 rsurface.inversematrix = *inversematrix;
8008 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8009 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8010 R_EntityMatrix(&rsurface.matrix);
8011 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8012 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8013 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8014 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8015 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8016 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8017 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8018 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8019 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8020 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8021 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8022 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8023 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);
8024 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8025 rsurface.frameblend[0].lerp = 1;
8026 rsurface.ent_alttextures = false;
8027 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8028 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8031 rsurface.modelvertex3f = (float *)vertex3f;
8032 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8033 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8034 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8036 else if (wantnormals)
8038 rsurface.modelvertex3f = (float *)vertex3f;
8039 rsurface.modelsvector3f = NULL;
8040 rsurface.modeltvector3f = NULL;
8041 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8045 rsurface.modelvertex3f = (float *)vertex3f;
8046 rsurface.modelsvector3f = NULL;
8047 rsurface.modeltvector3f = NULL;
8048 rsurface.modelnormal3f = NULL;
8050 rsurface.modelvertexmesh = NULL;
8051 rsurface.modelvertexmeshbuffer = NULL;
8052 rsurface.modelvertex3fbuffer = NULL;
8053 rsurface.modelvertex3f_vertexbuffer = 0;
8054 rsurface.modelvertex3f_bufferoffset = 0;
8055 rsurface.modelsvector3f_vertexbuffer = 0;
8056 rsurface.modelsvector3f_bufferoffset = 0;
8057 rsurface.modeltvector3f_vertexbuffer = 0;
8058 rsurface.modeltvector3f_bufferoffset = 0;
8059 rsurface.modelnormal3f_vertexbuffer = 0;
8060 rsurface.modelnormal3f_bufferoffset = 0;
8061 rsurface.modelgeneratedvertex = true;
8062 rsurface.modellightmapcolor4f = (float *)color4f;
8063 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8064 rsurface.modellightmapcolor4f_bufferoffset = 0;
8065 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8066 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8067 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8068 rsurface.modeltexcoordlightmap2f = NULL;
8069 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8070 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8071 rsurface.modelelement3i = (int *)element3i;
8072 rsurface.modelelement3i_indexbuffer = NULL;
8073 rsurface.modelelement3i_bufferoffset = 0;
8074 rsurface.modelelement3s = (unsigned short *)element3s;
8075 rsurface.modelelement3s_indexbuffer = NULL;
8076 rsurface.modelelement3s_bufferoffset = 0;
8077 rsurface.modellightmapoffsets = NULL;
8078 rsurface.modelsurfaces = NULL;
8079 rsurface.batchgeneratedvertex = false;
8080 rsurface.batchfirstvertex = 0;
8081 rsurface.batchnumvertices = 0;
8082 rsurface.batchfirsttriangle = 0;
8083 rsurface.batchnumtriangles = 0;
8084 rsurface.batchvertex3f = NULL;
8085 rsurface.batchvertex3f_vertexbuffer = NULL;
8086 rsurface.batchvertex3f_bufferoffset = 0;
8087 rsurface.batchsvector3f = NULL;
8088 rsurface.batchsvector3f_vertexbuffer = NULL;
8089 rsurface.batchsvector3f_bufferoffset = 0;
8090 rsurface.batchtvector3f = NULL;
8091 rsurface.batchtvector3f_vertexbuffer = NULL;
8092 rsurface.batchtvector3f_bufferoffset = 0;
8093 rsurface.batchnormal3f = NULL;
8094 rsurface.batchnormal3f_vertexbuffer = NULL;
8095 rsurface.batchnormal3f_bufferoffset = 0;
8096 rsurface.batchlightmapcolor4f = NULL;
8097 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8098 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8099 rsurface.batchtexcoordtexture2f = NULL;
8100 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8101 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8102 rsurface.batchtexcoordlightmap2f = NULL;
8103 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8104 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8105 rsurface.batchvertexmesh = NULL;
8106 rsurface.batchvertexmeshbuffer = NULL;
8107 rsurface.batchvertex3fbuffer = NULL;
8108 rsurface.batchelement3i = NULL;
8109 rsurface.batchelement3i_indexbuffer = NULL;
8110 rsurface.batchelement3i_bufferoffset = 0;
8111 rsurface.batchelement3s = NULL;
8112 rsurface.batchelement3s_indexbuffer = NULL;
8113 rsurface.batchelement3s_bufferoffset = 0;
8114 rsurface.passcolor4f = NULL;
8115 rsurface.passcolor4f_vertexbuffer = NULL;
8116 rsurface.passcolor4f_bufferoffset = 0;
8118 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8120 if ((wantnormals || wanttangents) && !normal3f)
8122 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8123 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8125 if (wanttangents && !svector3f)
8127 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8128 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8129 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8134 float RSurf_FogPoint(const float *v)
8136 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8137 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8138 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8139 float FogHeightFade = r_refdef.fogheightfade;
8141 unsigned int fogmasktableindex;
8142 if (r_refdef.fogplaneviewabove)
8143 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8145 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8146 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8147 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8150 float RSurf_FogVertex(const float *v)
8152 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8153 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8154 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8155 float FogHeightFade = rsurface.fogheightfade;
8157 unsigned int fogmasktableindex;
8158 if (r_refdef.fogplaneviewabove)
8159 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8161 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8162 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8163 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8166 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8169 for (i = 0;i < numelements;i++)
8170 outelement3i[i] = inelement3i[i] + adjust;
8173 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8174 extern cvar_t gl_vbo;
8175 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8183 int surfacefirsttriangle;
8184 int surfacenumtriangles;
8185 int surfacefirstvertex;
8186 int surfaceendvertex;
8187 int surfacenumvertices;
8188 int batchnumvertices;
8189 int batchnumtriangles;
8193 qboolean dynamicvertex;
8197 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8199 q3shaderinfo_deform_t *deform;
8200 const msurface_t *surface, *firstsurface;
8201 r_vertexmesh_t *vertexmesh;
8202 if (!texturenumsurfaces)
8204 // find vertex range of this surface batch
8206 firstsurface = texturesurfacelist[0];
8207 firsttriangle = firstsurface->num_firsttriangle;
8208 batchnumvertices = 0;
8209 batchnumtriangles = 0;
8210 firstvertex = endvertex = firstsurface->num_firstvertex;
8211 for (i = 0;i < texturenumsurfaces;i++)
8213 surface = texturesurfacelist[i];
8214 if (surface != firstsurface + i)
8216 surfacefirstvertex = surface->num_firstvertex;
8217 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8218 surfacenumvertices = surface->num_vertices;
8219 surfacenumtriangles = surface->num_triangles;
8220 if (firstvertex > surfacefirstvertex)
8221 firstvertex = surfacefirstvertex;
8222 if (endvertex < surfaceendvertex)
8223 endvertex = surfaceendvertex;
8224 batchnumvertices += surfacenumvertices;
8225 batchnumtriangles += surfacenumtriangles;
8228 // we now know the vertex range used, and if there are any gaps in it
8229 rsurface.batchfirstvertex = firstvertex;
8230 rsurface.batchnumvertices = endvertex - firstvertex;
8231 rsurface.batchfirsttriangle = firsttriangle;
8232 rsurface.batchnumtriangles = batchnumtriangles;
8234 // this variable holds flags for which properties have been updated that
8235 // may require regenerating vertexmesh array...
8238 // check if any dynamic vertex processing must occur
8239 dynamicvertex = false;
8241 // if there is a chance of animated vertex colors, it's a dynamic batch
8242 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8244 dynamicvertex = true;
8245 batchneed |= BATCHNEED_NOGAPS;
8246 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8249 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8251 switch (deform->deform)
8254 case Q3DEFORM_PROJECTIONSHADOW:
8255 case Q3DEFORM_TEXT0:
8256 case Q3DEFORM_TEXT1:
8257 case Q3DEFORM_TEXT2:
8258 case Q3DEFORM_TEXT3:
8259 case Q3DEFORM_TEXT4:
8260 case Q3DEFORM_TEXT5:
8261 case Q3DEFORM_TEXT6:
8262 case Q3DEFORM_TEXT7:
8265 case Q3DEFORM_AUTOSPRITE:
8266 dynamicvertex = true;
8267 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8268 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8270 case Q3DEFORM_AUTOSPRITE2:
8271 dynamicvertex = true;
8272 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8273 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8275 case Q3DEFORM_NORMAL:
8276 dynamicvertex = true;
8277 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8278 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8281 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8282 break; // if wavefunc is a nop, ignore this transform
8283 dynamicvertex = true;
8284 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8285 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8287 case Q3DEFORM_BULGE:
8288 dynamicvertex = true;
8289 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8290 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8293 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8294 break; // if wavefunc is a nop, ignore this transform
8295 dynamicvertex = true;
8296 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8297 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8301 switch(rsurface.texture->tcgen.tcgen)
8304 case Q3TCGEN_TEXTURE:
8306 case Q3TCGEN_LIGHTMAP:
8307 dynamicvertex = true;
8308 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8309 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8311 case Q3TCGEN_VECTOR:
8312 dynamicvertex = true;
8313 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8314 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8316 case Q3TCGEN_ENVIRONMENT:
8317 dynamicvertex = true;
8318 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8319 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8322 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8324 dynamicvertex = true;
8325 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8326 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8329 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8331 dynamicvertex = true;
8332 batchneed |= BATCHNEED_NOGAPS;
8333 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8336 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8338 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8339 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8340 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8341 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8342 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8343 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8344 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8347 // when the model data has no vertex buffer (dynamic mesh), we need to
8349 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8350 batchneed |= BATCHNEED_NOGAPS;
8352 // if needsupdate, we have to do a dynamic vertex batch for sure
8353 if (needsupdate & batchneed)
8354 dynamicvertex = true;
8356 // see if we need to build vertexmesh from arrays
8357 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8358 dynamicvertex = true;
8360 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8361 // also some drivers strongly dislike firstvertex
8362 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8363 dynamicvertex = true;
8365 rsurface.batchvertex3f = rsurface.modelvertex3f;
8366 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8367 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8368 rsurface.batchsvector3f = rsurface.modelsvector3f;
8369 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8370 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8371 rsurface.batchtvector3f = rsurface.modeltvector3f;
8372 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8373 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8374 rsurface.batchnormal3f = rsurface.modelnormal3f;
8375 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8376 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8377 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8378 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8379 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8380 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8381 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8382 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8383 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8384 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8385 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8386 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8387 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8388 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8389 rsurface.batchelement3i = rsurface.modelelement3i;
8390 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8391 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8392 rsurface.batchelement3s = rsurface.modelelement3s;
8393 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8394 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8396 // if any dynamic vertex processing has to occur in software, we copy the
8397 // entire surface list together before processing to rebase the vertices
8398 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8400 // if any gaps exist and we do not have a static vertex buffer, we have to
8401 // copy the surface list together to avoid wasting upload bandwidth on the
8402 // vertices in the gaps.
8404 // if gaps exist and we have a static vertex buffer, we still have to
8405 // combine the index buffer ranges into one dynamic index buffer.
8407 // in all cases we end up with data that can be drawn in one call.
8411 // static vertex data, just set pointers...
8412 rsurface.batchgeneratedvertex = false;
8413 // if there are gaps, we want to build a combined index buffer,
8414 // otherwise use the original static buffer with an appropriate offset
8417 // build a new triangle elements array for this batch
8418 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8419 rsurface.batchfirsttriangle = 0;
8421 for (i = 0;i < texturenumsurfaces;i++)
8423 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8424 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8425 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8426 numtriangles += surfacenumtriangles;
8428 rsurface.batchelement3i_indexbuffer = NULL;
8429 rsurface.batchelement3i_bufferoffset = 0;
8430 rsurface.batchelement3s = NULL;
8431 rsurface.batchelement3s_indexbuffer = NULL;
8432 rsurface.batchelement3s_bufferoffset = 0;
8433 if (endvertex <= 65536)
8435 // make a 16bit (unsigned short) index array if possible
8436 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8437 for (i = 0;i < numtriangles*3;i++)
8438 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8444 // something needs software processing, do it for real...
8445 // we only directly handle separate array data in this case and then
8446 // generate interleaved data if needed...
8447 rsurface.batchgeneratedvertex = true;
8449 // now copy the vertex data into a combined array and make an index array
8450 // (this is what Quake3 does all the time)
8451 //if (gaps || rsurface.batchfirstvertex)
8453 rsurface.batchvertex3fbuffer = NULL;
8454 rsurface.batchvertexmesh = NULL;
8455 rsurface.batchvertexmeshbuffer = NULL;
8456 rsurface.batchvertex3f = NULL;
8457 rsurface.batchvertex3f_vertexbuffer = NULL;
8458 rsurface.batchvertex3f_bufferoffset = 0;
8459 rsurface.batchsvector3f = NULL;
8460 rsurface.batchsvector3f_vertexbuffer = NULL;
8461 rsurface.batchsvector3f_bufferoffset = 0;
8462 rsurface.batchtvector3f = NULL;
8463 rsurface.batchtvector3f_vertexbuffer = NULL;
8464 rsurface.batchtvector3f_bufferoffset = 0;
8465 rsurface.batchnormal3f = NULL;
8466 rsurface.batchnormal3f_vertexbuffer = NULL;
8467 rsurface.batchnormal3f_bufferoffset = 0;
8468 rsurface.batchlightmapcolor4f = NULL;
8469 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8470 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8471 rsurface.batchtexcoordtexture2f = NULL;
8472 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8473 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8474 rsurface.batchtexcoordlightmap2f = NULL;
8475 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8476 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8477 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8478 rsurface.batchelement3i_indexbuffer = NULL;
8479 rsurface.batchelement3i_bufferoffset = 0;
8480 rsurface.batchelement3s = NULL;
8481 rsurface.batchelement3s_indexbuffer = NULL;
8482 rsurface.batchelement3s_bufferoffset = 0;
8483 // we'll only be setting up certain arrays as needed
8484 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8485 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8486 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8487 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8488 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8489 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8490 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8492 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8493 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8495 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8496 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8497 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8498 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8499 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8500 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8503 for (i = 0;i < texturenumsurfaces;i++)
8505 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8506 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8507 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8508 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8509 // copy only the data requested
8510 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8511 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8512 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8514 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8515 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8516 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8517 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8518 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8520 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8521 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8523 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8524 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8525 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8526 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8527 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8528 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8530 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8531 numvertices += surfacenumvertices;
8532 numtriangles += surfacenumtriangles;
8535 // generate a 16bit index array as well if possible
8536 // (in general, dynamic batches fit)
8537 if (numvertices <= 65536)
8539 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8540 for (i = 0;i < numtriangles*3;i++)
8541 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8544 // since we've copied everything, the batch now starts at 0
8545 rsurface.batchfirstvertex = 0;
8546 rsurface.batchnumvertices = batchnumvertices;
8547 rsurface.batchfirsttriangle = 0;
8548 rsurface.batchnumtriangles = batchnumtriangles;
8551 // q1bsp surfaces rendered in vertex color mode have to have colors
8552 // calculated based on lightstyles
8553 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8555 // generate color arrays for the surfaces in this list
8560 const unsigned char *lm;
8561 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8562 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8563 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8565 for (i = 0;i < texturenumsurfaces;i++)
8567 surface = texturesurfacelist[i];
8568 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8569 surfacenumvertices = surface->num_vertices;
8570 if (surface->lightmapinfo->samples)
8572 for (j = 0;j < surfacenumvertices;j++)
8574 lm = surface->lightmapinfo->samples + offsets[j];
8575 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8576 VectorScale(lm, scale, c);
8577 if (surface->lightmapinfo->styles[1] != 255)
8579 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8581 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8582 VectorMA(c, scale, lm, c);
8583 if (surface->lightmapinfo->styles[2] != 255)
8586 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8587 VectorMA(c, scale, lm, c);
8588 if (surface->lightmapinfo->styles[3] != 255)
8591 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8592 VectorMA(c, scale, lm, c);
8599 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);
8605 for (j = 0;j < surfacenumvertices;j++)
8607 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8614 // if vertices are deformed (sprite flares and things in maps, possibly
8615 // water waves, bulges and other deformations), modify the copied vertices
8617 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8619 switch (deform->deform)
8622 case Q3DEFORM_PROJECTIONSHADOW:
8623 case Q3DEFORM_TEXT0:
8624 case Q3DEFORM_TEXT1:
8625 case Q3DEFORM_TEXT2:
8626 case Q3DEFORM_TEXT3:
8627 case Q3DEFORM_TEXT4:
8628 case Q3DEFORM_TEXT5:
8629 case Q3DEFORM_TEXT6:
8630 case Q3DEFORM_TEXT7:
8633 case Q3DEFORM_AUTOSPRITE:
8634 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8635 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8636 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8637 VectorNormalize(newforward);
8638 VectorNormalize(newright);
8639 VectorNormalize(newup);
8640 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8641 // rsurface.batchvertex3f_vertexbuffer = NULL;
8642 // rsurface.batchvertex3f_bufferoffset = 0;
8643 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8644 // rsurface.batchsvector3f_vertexbuffer = NULL;
8645 // rsurface.batchsvector3f_bufferoffset = 0;
8646 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8647 // rsurface.batchtvector3f_vertexbuffer = NULL;
8648 // rsurface.batchtvector3f_bufferoffset = 0;
8649 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8650 // rsurface.batchnormal3f_vertexbuffer = NULL;
8651 // rsurface.batchnormal3f_bufferoffset = 0;
8652 // a single autosprite surface can contain multiple sprites...
8653 for (j = 0;j < batchnumvertices - 3;j += 4)
8655 VectorClear(center);
8656 for (i = 0;i < 4;i++)
8657 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8658 VectorScale(center, 0.25f, center);
8659 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8660 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8661 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8662 for (i = 0;i < 4;i++)
8664 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8665 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8668 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8669 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8670 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);
8672 case Q3DEFORM_AUTOSPRITE2:
8673 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8674 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8675 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8676 VectorNormalize(newforward);
8677 VectorNormalize(newright);
8678 VectorNormalize(newup);
8679 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8680 // rsurface.batchvertex3f_vertexbuffer = NULL;
8681 // rsurface.batchvertex3f_bufferoffset = 0;
8683 const float *v1, *v2;
8693 memset(shortest, 0, sizeof(shortest));
8694 // a single autosprite surface can contain multiple sprites...
8695 for (j = 0;j < batchnumvertices - 3;j += 4)
8697 VectorClear(center);
8698 for (i = 0;i < 4;i++)
8699 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8700 VectorScale(center, 0.25f, center);
8701 // find the two shortest edges, then use them to define the
8702 // axis vectors for rotating around the central axis
8703 for (i = 0;i < 6;i++)
8705 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8706 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8707 l = VectorDistance2(v1, v2);
8708 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8710 l += (1.0f / 1024.0f);
8711 if (shortest[0].length2 > l || i == 0)
8713 shortest[1] = shortest[0];
8714 shortest[0].length2 = l;
8715 shortest[0].v1 = v1;
8716 shortest[0].v2 = v2;
8718 else if (shortest[1].length2 > l || i == 1)
8720 shortest[1].length2 = l;
8721 shortest[1].v1 = v1;
8722 shortest[1].v2 = v2;
8725 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8726 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8727 // this calculates the right vector from the shortest edge
8728 // and the up vector from the edge midpoints
8729 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8730 VectorNormalize(right);
8731 VectorSubtract(end, start, up);
8732 VectorNormalize(up);
8733 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8734 VectorSubtract(rsurface.localvieworigin, center, forward);
8735 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8736 VectorNegate(forward, forward);
8737 VectorReflect(forward, 0, up, forward);
8738 VectorNormalize(forward);
8739 CrossProduct(up, forward, newright);
8740 VectorNormalize(newright);
8741 // rotate the quad around the up axis vector, this is made
8742 // especially easy by the fact we know the quad is flat,
8743 // so we only have to subtract the center position and
8744 // measure distance along the right vector, and then
8745 // multiply that by the newright vector and add back the
8747 // we also need to subtract the old position to undo the
8748 // displacement from the center, which we do with a
8749 // DotProduct, the subtraction/addition of center is also
8750 // optimized into DotProducts here
8751 l = DotProduct(right, center);
8752 for (i = 0;i < 4;i++)
8754 v1 = rsurface.batchvertex3f + 3*(j+i);
8755 f = DotProduct(right, v1) - l;
8756 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8760 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8762 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8763 // rsurface.batchnormal3f_vertexbuffer = NULL;
8764 // rsurface.batchnormal3f_bufferoffset = 0;
8765 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8767 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8769 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8770 // rsurface.batchsvector3f_vertexbuffer = NULL;
8771 // rsurface.batchsvector3f_bufferoffset = 0;
8772 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8773 // rsurface.batchtvector3f_vertexbuffer = NULL;
8774 // rsurface.batchtvector3f_bufferoffset = 0;
8775 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);
8778 case Q3DEFORM_NORMAL:
8779 // deform the normals to make reflections wavey
8780 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8781 rsurface.batchnormal3f_vertexbuffer = NULL;
8782 rsurface.batchnormal3f_bufferoffset = 0;
8783 for (j = 0;j < batchnumvertices;j++)
8786 float *normal = rsurface.batchnormal3f + 3*j;
8787 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8788 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8789 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]);
8790 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]);
8791 VectorNormalize(normal);
8793 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8795 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8796 // rsurface.batchsvector3f_vertexbuffer = NULL;
8797 // rsurface.batchsvector3f_bufferoffset = 0;
8798 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8799 // rsurface.batchtvector3f_vertexbuffer = NULL;
8800 // rsurface.batchtvector3f_bufferoffset = 0;
8801 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);
8805 // deform vertex array to make wavey water and flags and such
8806 waveparms[0] = deform->waveparms[0];
8807 waveparms[1] = deform->waveparms[1];
8808 waveparms[2] = deform->waveparms[2];
8809 waveparms[3] = deform->waveparms[3];
8810 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8811 break; // if wavefunc is a nop, don't make a dynamic vertex array
8812 // this is how a divisor of vertex influence on deformation
8813 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8814 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8815 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8816 // rsurface.batchvertex3f_vertexbuffer = NULL;
8817 // rsurface.batchvertex3f_bufferoffset = 0;
8818 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8819 // rsurface.batchnormal3f_vertexbuffer = NULL;
8820 // rsurface.batchnormal3f_bufferoffset = 0;
8821 for (j = 0;j < batchnumvertices;j++)
8823 // if the wavefunc depends on time, evaluate it per-vertex
8826 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8827 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8829 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8831 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8832 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8833 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8835 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8836 // rsurface.batchsvector3f_vertexbuffer = NULL;
8837 // rsurface.batchsvector3f_bufferoffset = 0;
8838 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8839 // rsurface.batchtvector3f_vertexbuffer = NULL;
8840 // rsurface.batchtvector3f_bufferoffset = 0;
8841 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);
8844 case Q3DEFORM_BULGE:
8845 // deform vertex array to make the surface have moving bulges
8846 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8847 // rsurface.batchvertex3f_vertexbuffer = NULL;
8848 // rsurface.batchvertex3f_bufferoffset = 0;
8849 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8850 // rsurface.batchnormal3f_vertexbuffer = NULL;
8851 // rsurface.batchnormal3f_bufferoffset = 0;
8852 for (j = 0;j < batchnumvertices;j++)
8854 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8855 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8857 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8858 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8859 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8861 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8862 // rsurface.batchsvector3f_vertexbuffer = NULL;
8863 // rsurface.batchsvector3f_bufferoffset = 0;
8864 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8865 // rsurface.batchtvector3f_vertexbuffer = NULL;
8866 // rsurface.batchtvector3f_bufferoffset = 0;
8867 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);
8871 // deform vertex array
8872 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8873 break; // if wavefunc is a nop, don't make a dynamic vertex array
8874 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8875 VectorScale(deform->parms, scale, waveparms);
8876 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8877 // rsurface.batchvertex3f_vertexbuffer = NULL;
8878 // rsurface.batchvertex3f_bufferoffset = 0;
8879 for (j = 0;j < batchnumvertices;j++)
8880 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8885 // generate texcoords based on the chosen texcoord source
8886 switch(rsurface.texture->tcgen.tcgen)
8889 case Q3TCGEN_TEXTURE:
8891 case Q3TCGEN_LIGHTMAP:
8892 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8893 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8894 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8895 if (rsurface.batchtexcoordlightmap2f)
8896 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8898 case Q3TCGEN_VECTOR:
8899 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8900 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8901 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8902 for (j = 0;j < batchnumvertices;j++)
8904 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8905 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8908 case Q3TCGEN_ENVIRONMENT:
8909 // make environment reflections using a spheremap
8910 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8911 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8912 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8913 for (j = 0;j < batchnumvertices;j++)
8915 // identical to Q3A's method, but executed in worldspace so
8916 // carried models can be shiny too
8918 float viewer[3], d, reflected[3], worldreflected[3];
8920 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8921 // VectorNormalize(viewer);
8923 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8925 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8926 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8927 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8928 // note: this is proportinal to viewer, so we can normalize later
8930 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8931 VectorNormalize(worldreflected);
8933 // note: this sphere map only uses world x and z!
8934 // so positive and negative y will LOOK THE SAME.
8935 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8936 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8940 // the only tcmod that needs software vertex processing is turbulent, so
8941 // check for it here and apply the changes if needed
8942 // and we only support that as the first one
8943 // (handling a mixture of turbulent and other tcmods would be problematic
8944 // without punting it entirely to a software path)
8945 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8947 amplitude = rsurface.texture->tcmods[0].parms[1];
8948 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8949 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8950 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8951 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8952 for (j = 0;j < batchnumvertices;j++)
8954 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);
8955 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8959 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8961 // convert the modified arrays to vertex structs
8962 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8963 // rsurface.batchvertexmeshbuffer = NULL;
8964 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8965 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8966 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8967 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8968 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8969 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
8970 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
8972 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8974 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
8975 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
8978 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
8979 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8980 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
8981 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
8982 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8983 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
8984 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
8985 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8986 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
8990 void RSurf_DrawBatch(void)
8992 // sometimes a zero triangle surface (usually a degenerate patch) makes it
8993 // through the pipeline, killing it earlier in the pipeline would have
8994 // per-surface overhead rather than per-batch overhead, so it's best to
8995 // reject it here, before it hits glDraw.
8996 if (rsurface.batchnumtriangles == 0)
8999 // batch debugging code
9000 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9006 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9007 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9010 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9012 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9014 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9015 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);
9022 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);
9025 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9027 // pick the closest matching water plane
9028 int planeindex, vertexindex, bestplaneindex = -1;
9032 r_waterstate_waterplane_t *p;
9033 qboolean prepared = false;
9035 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9037 if(p->camera_entity != rsurface.texture->camera_entity)
9042 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9044 if(rsurface.batchnumvertices == 0)
9047 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9049 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9050 d += fabs(PlaneDiff(vert, &p->plane));
9052 if (bestd > d || bestplaneindex < 0)
9055 bestplaneindex = planeindex;
9058 return bestplaneindex;
9059 // NOTE: this MAY return a totally unrelated water plane; we can ignore
9060 // this situation though, as it might be better to render single larger
9061 // batches with useless stuff (backface culled for example) than to
9062 // render multiple smaller batches
9065 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9068 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9069 rsurface.passcolor4f_vertexbuffer = 0;
9070 rsurface.passcolor4f_bufferoffset = 0;
9071 for (i = 0;i < rsurface.batchnumvertices;i++)
9072 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9075 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9082 if (rsurface.passcolor4f)
9084 // generate color arrays
9085 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9086 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9087 rsurface.passcolor4f_vertexbuffer = 0;
9088 rsurface.passcolor4f_bufferoffset = 0;
9089 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)
9091 f = RSurf_FogVertex(v);
9100 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9101 rsurface.passcolor4f_vertexbuffer = 0;
9102 rsurface.passcolor4f_bufferoffset = 0;
9103 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9105 f = RSurf_FogVertex(v);
9114 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9121 if (!rsurface.passcolor4f)
9123 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9124 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9125 rsurface.passcolor4f_vertexbuffer = 0;
9126 rsurface.passcolor4f_bufferoffset = 0;
9127 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)
9129 f = RSurf_FogVertex(v);
9130 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9131 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9132 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9137 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9142 if (!rsurface.passcolor4f)
9144 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9145 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9146 rsurface.passcolor4f_vertexbuffer = 0;
9147 rsurface.passcolor4f_bufferoffset = 0;
9148 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9157 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9162 if (!rsurface.passcolor4f)
9164 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9165 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9166 rsurface.passcolor4f_vertexbuffer = 0;
9167 rsurface.passcolor4f_bufferoffset = 0;
9168 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9170 c2[0] = c[0] + r_refdef.scene.ambient;
9171 c2[1] = c[1] + r_refdef.scene.ambient;
9172 c2[2] = c[2] + r_refdef.scene.ambient;
9177 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9180 rsurface.passcolor4f = NULL;
9181 rsurface.passcolor4f_vertexbuffer = 0;
9182 rsurface.passcolor4f_bufferoffset = 0;
9183 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9184 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9185 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9186 GL_Color(r, g, b, a);
9187 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9191 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9193 // TODO: optimize applyfog && applycolor case
9194 // just apply fog if necessary, and tint the fog color array if necessary
9195 rsurface.passcolor4f = NULL;
9196 rsurface.passcolor4f_vertexbuffer = 0;
9197 rsurface.passcolor4f_bufferoffset = 0;
9198 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9199 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9200 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9201 GL_Color(r, g, b, a);
9205 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9208 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9209 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9210 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9211 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9212 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9213 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9214 GL_Color(r, g, b, a);
9218 static void RSurf_DrawBatch_GL11_ClampColor(void)
9223 if (!rsurface.passcolor4f)
9225 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9227 c2[0] = bound(0.0f, c1[0], 1.0f);
9228 c2[1] = bound(0.0f, c1[1], 1.0f);
9229 c2[2] = bound(0.0f, c1[2], 1.0f);
9230 c2[3] = bound(0.0f, c1[3], 1.0f);
9234 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9244 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9245 rsurface.passcolor4f_vertexbuffer = 0;
9246 rsurface.passcolor4f_bufferoffset = 0;
9247 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)
9249 f = -DotProduct(r_refdef.view.forward, n);
9251 f = f * 0.85 + 0.15; // work around so stuff won't get black
9252 f *= r_refdef.lightmapintensity;
9253 Vector4Set(c, f, f, f, 1);
9257 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9259 RSurf_DrawBatch_GL11_ApplyFakeLight();
9260 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9261 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9262 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9263 GL_Color(r, g, b, a);
9267 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9275 vec3_t ambientcolor;
9276 vec3_t diffusecolor;
9280 VectorCopy(rsurface.modellight_lightdir, lightdir);
9281 f = 0.5f * r_refdef.lightmapintensity;
9282 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9283 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9284 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9285 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9286 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9287 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9289 if (VectorLength2(diffusecolor) > 0)
9291 // q3-style directional shading
9292 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9293 rsurface.passcolor4f_vertexbuffer = 0;
9294 rsurface.passcolor4f_bufferoffset = 0;
9295 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)
9297 if ((f = DotProduct(n, lightdir)) > 0)
9298 VectorMA(ambientcolor, f, diffusecolor, c);
9300 VectorCopy(ambientcolor, c);
9307 *applycolor = false;
9311 *r = ambientcolor[0];
9312 *g = ambientcolor[1];
9313 *b = ambientcolor[2];
9314 rsurface.passcolor4f = NULL;
9315 rsurface.passcolor4f_vertexbuffer = 0;
9316 rsurface.passcolor4f_bufferoffset = 0;
9320 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9322 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9323 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9324 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9325 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9326 GL_Color(r, g, b, a);
9330 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9338 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9339 rsurface.passcolor4f_vertexbuffer = 0;
9340 rsurface.passcolor4f_bufferoffset = 0;
9342 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9344 f = 1 - RSurf_FogVertex(v);
9352 void RSurf_SetupDepthAndCulling(void)
9354 // submodels are biased to avoid z-fighting with world surfaces that they
9355 // may be exactly overlapping (avoids z-fighting artifacts on certain
9356 // doors and things in Quake maps)
9357 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9358 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9359 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9360 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9363 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9365 // transparent sky would be ridiculous
9366 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9368 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9369 skyrenderlater = true;
9370 RSurf_SetupDepthAndCulling();
9372 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9373 // skymasking on them, and Quake3 never did sky masking (unlike
9374 // software Quake and software Quake2), so disable the sky masking
9375 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9376 // and skymasking also looks very bad when noclipping outside the
9377 // level, so don't use it then either.
9378 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9380 R_Mesh_ResetTextureState();
9381 if (skyrendermasked)
9383 R_SetupShader_DepthOrShadow();
9384 // depth-only (masking)
9385 GL_ColorMask(0,0,0,0);
9386 // just to make sure that braindead drivers don't draw
9387 // anything despite that colormask...
9388 GL_BlendFunc(GL_ZERO, GL_ONE);
9389 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9390 if (rsurface.batchvertex3fbuffer)
9391 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9393 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9397 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9399 GL_BlendFunc(GL_ONE, GL_ZERO);
9400 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9401 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9402 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9405 if (skyrendermasked)
9406 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9408 R_Mesh_ResetTextureState();
9409 GL_Color(1, 1, 1, 1);
9412 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9413 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9414 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9416 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9420 // render screenspace normalmap to texture
9422 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9427 // bind lightmap texture
9429 // water/refraction/reflection/camera surfaces have to be handled specially
9430 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9432 int start, end, startplaneindex;
9433 for (start = 0;start < texturenumsurfaces;start = end)
9435 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9436 if(startplaneindex < 0)
9438 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9439 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9443 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9445 // now that we have a batch using the same planeindex, render it
9446 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9448 // render water or distortion background
9450 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));
9452 // blend surface on top
9453 GL_DepthMask(false);
9454 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9457 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9459 // render surface with reflection texture as input
9460 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9461 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));
9468 // render surface batch normally
9469 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9470 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9474 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9476 // OpenGL 1.3 path - anything not completely ancient
9477 qboolean applycolor;
9480 const texturelayer_t *layer;
9481 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);
9482 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9484 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9487 int layertexrgbscale;
9488 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9490 if (layerindex == 0)
9494 GL_AlphaTest(false);
9495 GL_DepthFunc(GL_EQUAL);
9498 GL_DepthMask(layer->depthmask && writedepth);
9499 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9500 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9502 layertexrgbscale = 4;
9503 VectorScale(layer->color, 0.25f, layercolor);
9505 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9507 layertexrgbscale = 2;
9508 VectorScale(layer->color, 0.5f, layercolor);
9512 layertexrgbscale = 1;
9513 VectorScale(layer->color, 1.0f, layercolor);
9515 layercolor[3] = layer->color[3];
9516 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9517 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9518 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9519 switch (layer->type)
9521 case TEXTURELAYERTYPE_LITTEXTURE:
9522 // single-pass lightmapped texture with 2x rgbscale
9523 R_Mesh_TexBind(0, r_texture_white);
9524 R_Mesh_TexMatrix(0, NULL);
9525 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9526 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9527 R_Mesh_TexBind(1, layer->texture);
9528 R_Mesh_TexMatrix(1, &layer->texmatrix);
9529 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9530 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9531 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9532 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9533 else if (FAKELIGHT_ENABLED)
9534 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9535 else if (rsurface.uselightmaptexture)
9536 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9538 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9540 case TEXTURELAYERTYPE_TEXTURE:
9541 // singletexture unlit texture with transparency support
9542 R_Mesh_TexBind(0, layer->texture);
9543 R_Mesh_TexMatrix(0, &layer->texmatrix);
9544 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9545 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9546 R_Mesh_TexBind(1, 0);
9547 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9548 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9550 case TEXTURELAYERTYPE_FOG:
9551 // singletexture fogging
9554 R_Mesh_TexBind(0, layer->texture);
9555 R_Mesh_TexMatrix(0, &layer->texmatrix);
9556 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9557 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9561 R_Mesh_TexBind(0, 0);
9562 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9564 R_Mesh_TexBind(1, 0);
9565 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9566 // generate a color array for the fog pass
9567 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9568 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9572 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9575 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9577 GL_DepthFunc(GL_LEQUAL);
9578 GL_AlphaTest(false);
9582 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9584 // OpenGL 1.1 - crusty old voodoo path
9587 const texturelayer_t *layer;
9588 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);
9589 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9591 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9593 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9595 if (layerindex == 0)
9599 GL_AlphaTest(false);
9600 GL_DepthFunc(GL_EQUAL);
9603 GL_DepthMask(layer->depthmask && writedepth);
9604 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9605 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9606 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9607 switch (layer->type)
9609 case TEXTURELAYERTYPE_LITTEXTURE:
9610 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9612 // two-pass lit texture with 2x rgbscale
9613 // first the lightmap pass
9614 R_Mesh_TexBind(0, r_texture_white);
9615 R_Mesh_TexMatrix(0, NULL);
9616 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9617 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9618 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9619 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9620 else if (FAKELIGHT_ENABLED)
9621 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9622 else if (rsurface.uselightmaptexture)
9623 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9625 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9626 // then apply the texture to it
9627 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9628 R_Mesh_TexBind(0, layer->texture);
9629 R_Mesh_TexMatrix(0, &layer->texmatrix);
9630 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9631 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9632 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);
9636 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9637 R_Mesh_TexBind(0, layer->texture);
9638 R_Mesh_TexMatrix(0, &layer->texmatrix);
9639 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9640 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9641 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9642 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);
9644 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);
9647 case TEXTURELAYERTYPE_TEXTURE:
9648 // singletexture unlit texture with transparency support
9649 R_Mesh_TexBind(0, layer->texture);
9650 R_Mesh_TexMatrix(0, &layer->texmatrix);
9651 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9652 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9653 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);
9655 case TEXTURELAYERTYPE_FOG:
9656 // singletexture fogging
9659 R_Mesh_TexBind(0, layer->texture);
9660 R_Mesh_TexMatrix(0, &layer->texmatrix);
9661 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9662 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9666 R_Mesh_TexBind(0, 0);
9667 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9669 // generate a color array for the fog pass
9670 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9671 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9675 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9678 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9680 GL_DepthFunc(GL_LEQUAL);
9681 GL_AlphaTest(false);
9685 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9689 r_vertexgeneric_t *batchvertex;
9692 // R_Mesh_ResetTextureState();
9693 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9695 if(rsurface.texture && rsurface.texture->currentskinframe)
9697 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9698 c[3] *= rsurface.texture->currentalpha;
9708 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9710 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9711 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9712 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9715 // brighten it up (as texture value 127 means "unlit")
9716 c[0] *= 2 * r_refdef.view.colorscale;
9717 c[1] *= 2 * r_refdef.view.colorscale;
9718 c[2] *= 2 * r_refdef.view.colorscale;
9720 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9721 c[3] *= r_wateralpha.value;
9723 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9725 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9726 GL_DepthMask(false);
9728 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9730 GL_BlendFunc(GL_ONE, GL_ONE);
9731 GL_DepthMask(false);
9733 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9735 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9736 GL_DepthMask(false);
9738 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9740 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9741 GL_DepthMask(false);
9745 GL_BlendFunc(GL_ONE, GL_ZERO);
9746 GL_DepthMask(writedepth);
9749 if (r_showsurfaces.integer == 3)
9751 rsurface.passcolor4f = NULL;
9753 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9755 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9757 rsurface.passcolor4f = NULL;
9758 rsurface.passcolor4f_vertexbuffer = 0;
9759 rsurface.passcolor4f_bufferoffset = 0;
9761 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9763 qboolean applycolor = true;
9766 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9768 r_refdef.lightmapintensity = 1;
9769 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9770 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9772 else if (FAKELIGHT_ENABLED)
9774 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9776 r_refdef.lightmapintensity = r_fakelight_intensity.value;
9777 RSurf_DrawBatch_GL11_ApplyFakeLight();
9778 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9782 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9784 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9785 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9786 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9789 if(!rsurface.passcolor4f)
9790 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9792 RSurf_DrawBatch_GL11_ApplyAmbient();
9793 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9794 if(r_refdef.fogenabled)
9795 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9796 RSurf_DrawBatch_GL11_ClampColor();
9798 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9799 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9802 else if (!r_refdef.view.showdebug)
9804 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9805 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9806 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9808 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9809 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9811 R_Mesh_PrepareVertices_Generic_Unlock();
9814 else if (r_showsurfaces.integer == 4)
9816 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9817 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9818 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9820 unsigned char c = (vi << 3) * (1.0f / 256.0f);
9821 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9822 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9824 R_Mesh_PrepareVertices_Generic_Unlock();
9827 else if (r_showsurfaces.integer == 2)
9830 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9831 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9832 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9834 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9835 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9836 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9837 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9838 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9839 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9840 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9842 R_Mesh_PrepareVertices_Generic_Unlock();
9843 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9847 int texturesurfaceindex;
9849 const msurface_t *surface;
9850 float surfacecolor4f[4];
9851 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9852 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9854 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9856 surface = texturesurfacelist[texturesurfaceindex];
9857 k = (int)(((size_t)surface) / sizeof(msurface_t));
9858 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9859 for (j = 0;j < surface->num_vertices;j++)
9861 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9862 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9866 R_Mesh_PrepareVertices_Generic_Unlock();
9871 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9874 RSurf_SetupDepthAndCulling();
9875 if (r_showsurfaces.integer)
9877 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9880 switch (vid.renderpath)
9882 case RENDERPATH_GL20:
9883 case RENDERPATH_D3D9:
9884 case RENDERPATH_D3D10:
9885 case RENDERPATH_D3D11:
9886 case RENDERPATH_SOFT:
9887 case RENDERPATH_GLES2:
9888 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9890 case RENDERPATH_GL13:
9891 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9893 case RENDERPATH_GL11:
9894 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9900 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9903 RSurf_SetupDepthAndCulling();
9904 if (r_showsurfaces.integer)
9906 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9909 switch (vid.renderpath)
9911 case RENDERPATH_GL20:
9912 case RENDERPATH_D3D9:
9913 case RENDERPATH_D3D10:
9914 case RENDERPATH_D3D11:
9915 case RENDERPATH_SOFT:
9916 case RENDERPATH_GLES2:
9917 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9919 case RENDERPATH_GL13:
9920 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9922 case RENDERPATH_GL11:
9923 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9929 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9932 int texturenumsurfaces, endsurface;
9934 const msurface_t *surface;
9935 #define MAXBATCH_TRANSPARENTSURFACES 256
9936 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9938 // if the model is static it doesn't matter what value we give for
9939 // wantnormals and wanttangents, so this logic uses only rules applicable
9940 // to a model, knowing that they are meaningless otherwise
9941 if (ent == r_refdef.scene.worldentity)
9942 RSurf_ActiveWorldEntity();
9943 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9944 RSurf_ActiveModelEntity(ent, false, false, false);
9947 switch (vid.renderpath)
9949 case RENDERPATH_GL20:
9950 case RENDERPATH_D3D9:
9951 case RENDERPATH_D3D10:
9952 case RENDERPATH_D3D11:
9953 case RENDERPATH_SOFT:
9954 case RENDERPATH_GLES2:
9955 RSurf_ActiveModelEntity(ent, true, true, false);
9957 case RENDERPATH_GL13:
9958 case RENDERPATH_GL11:
9959 RSurf_ActiveModelEntity(ent, true, false, false);
9964 if (r_transparentdepthmasking.integer)
9966 qboolean setup = false;
9967 for (i = 0;i < numsurfaces;i = j)
9970 surface = rsurface.modelsurfaces + surfacelist[i];
9971 texture = surface->texture;
9972 rsurface.texture = R_GetCurrentTexture(texture);
9973 rsurface.lightmaptexture = NULL;
9974 rsurface.deluxemaptexture = NULL;
9975 rsurface.uselightmaptexture = false;
9976 // scan ahead until we find a different texture
9977 endsurface = min(i + 1024, numsurfaces);
9978 texturenumsurfaces = 0;
9979 texturesurfacelist[texturenumsurfaces++] = surface;
9980 for (;j < endsurface;j++)
9982 surface = rsurface.modelsurfaces + surfacelist[j];
9983 if (texture != surface->texture)
9985 texturesurfacelist[texturenumsurfaces++] = surface;
9987 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9989 // render the range of surfaces as depth
9993 GL_ColorMask(0,0,0,0);
9996 GL_BlendFunc(GL_ONE, GL_ZERO);
9998 // R_Mesh_ResetTextureState();
9999 R_SetupShader_DepthOrShadow();
10001 RSurf_SetupDepthAndCulling();
10002 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10003 if (rsurface.batchvertex3fbuffer)
10004 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10006 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10010 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10013 for (i = 0;i < numsurfaces;i = j)
10016 surface = rsurface.modelsurfaces + surfacelist[i];
10017 texture = surface->texture;
10018 rsurface.texture = R_GetCurrentTexture(texture);
10019 // scan ahead until we find a different texture
10020 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
10021 texturenumsurfaces = 0;
10022 texturesurfacelist[texturenumsurfaces++] = surface;
10023 if(FAKELIGHT_ENABLED)
10025 rsurface.lightmaptexture = NULL;
10026 rsurface.deluxemaptexture = NULL;
10027 rsurface.uselightmaptexture = false;
10028 for (;j < endsurface;j++)
10030 surface = rsurface.modelsurfaces + surfacelist[j];
10031 if (texture != surface->texture)
10033 texturesurfacelist[texturenumsurfaces++] = surface;
10038 rsurface.lightmaptexture = surface->lightmaptexture;
10039 rsurface.deluxemaptexture = surface->deluxemaptexture;
10040 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10041 for (;j < endsurface;j++)
10043 surface = rsurface.modelsurfaces + surfacelist[j];
10044 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10046 texturesurfacelist[texturenumsurfaces++] = surface;
10049 // render the range of surfaces
10050 if (ent == r_refdef.scene.worldentity)
10051 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10053 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10055 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10058 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10060 // transparent surfaces get pushed off into the transparent queue
10061 int surfacelistindex;
10062 const msurface_t *surface;
10063 vec3_t tempcenter, center;
10064 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10066 surface = texturesurfacelist[surfacelistindex];
10067 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10068 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10069 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10070 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10071 if (queueentity->transparent_offset) // transparent offset
10073 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10074 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10075 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10077 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10081 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10083 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10085 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10087 RSurf_SetupDepthAndCulling();
10088 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10089 if (rsurface.batchvertex3fbuffer)
10090 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10092 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10096 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10098 const entity_render_t *queueentity = r_refdef.scene.worldentity;
10101 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10104 if (!rsurface.texture->currentnumlayers)
10106 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10107 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10109 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10111 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10112 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10113 else if (!rsurface.texture->currentnumlayers)
10115 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10117 // in the deferred case, transparent surfaces were queued during prepass
10118 if (!r_shadow_usingdeferredprepass)
10119 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10123 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10124 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10129 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10132 texture_t *texture;
10133 R_FrameData_SetMark();
10134 // break the surface list down into batches by texture and use of lightmapping
10135 for (i = 0;i < numsurfaces;i = j)
10138 // texture is the base texture pointer, rsurface.texture is the
10139 // current frame/skin the texture is directing us to use (for example
10140 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10141 // use skin 1 instead)
10142 texture = surfacelist[i]->texture;
10143 rsurface.texture = R_GetCurrentTexture(texture);
10144 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10146 // if this texture is not the kind we want, skip ahead to the next one
10147 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10151 if(FAKELIGHT_ENABLED || depthonly || prepass)
10153 rsurface.lightmaptexture = NULL;
10154 rsurface.deluxemaptexture = NULL;
10155 rsurface.uselightmaptexture = false;
10156 // simply scan ahead until we find a different texture or lightmap state
10157 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10162 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10163 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10164 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10165 // simply scan ahead until we find a different texture or lightmap state
10166 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10169 // render the range of surfaces
10170 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10172 R_FrameData_ReturnToMark();
10175 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10179 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10182 if (!rsurface.texture->currentnumlayers)
10184 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10185 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10187 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10189 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10190 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10191 else if (!rsurface.texture->currentnumlayers)
10193 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10195 // in the deferred case, transparent surfaces were queued during prepass
10196 if (!r_shadow_usingdeferredprepass)
10197 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10201 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10202 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10207 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10210 texture_t *texture;
10211 R_FrameData_SetMark();
10212 // break the surface list down into batches by texture and use of lightmapping
10213 for (i = 0;i < numsurfaces;i = j)
10216 // texture is the base texture pointer, rsurface.texture is the
10217 // current frame/skin the texture is directing us to use (for example
10218 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10219 // use skin 1 instead)
10220 texture = surfacelist[i]->texture;
10221 rsurface.texture = R_GetCurrentTexture(texture);
10222 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10224 // if this texture is not the kind we want, skip ahead to the next one
10225 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10229 if(FAKELIGHT_ENABLED || depthonly || prepass)
10231 rsurface.lightmaptexture = NULL;
10232 rsurface.deluxemaptexture = NULL;
10233 rsurface.uselightmaptexture = false;
10234 // simply scan ahead until we find a different texture or lightmap state
10235 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10240 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10241 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10242 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10243 // simply scan ahead until we find a different texture or lightmap state
10244 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10247 // render the range of surfaces
10248 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10250 R_FrameData_ReturnToMark();
10253 float locboxvertex3f[6*4*3] =
10255 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10256 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10257 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10258 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10259 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10260 1,0,0, 0,0,0, 0,1,0, 1,1,0
10263 unsigned short locboxelements[6*2*3] =
10268 12,13,14, 12,14,15,
10269 16,17,18, 16,18,19,
10273 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10276 cl_locnode_t *loc = (cl_locnode_t *)ent;
10278 float vertex3f[6*4*3];
10280 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10281 GL_DepthMask(false);
10282 GL_DepthRange(0, 1);
10283 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10284 GL_DepthTest(true);
10285 GL_CullFace(GL_NONE);
10286 R_EntityMatrix(&identitymatrix);
10288 // R_Mesh_ResetTextureState();
10290 i = surfacelist[0];
10291 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10292 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10293 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10294 surfacelist[0] < 0 ? 0.5f : 0.125f);
10296 if (VectorCompare(loc->mins, loc->maxs))
10298 VectorSet(size, 2, 2, 2);
10299 VectorMA(loc->mins, -0.5f, size, mins);
10303 VectorCopy(loc->mins, mins);
10304 VectorSubtract(loc->maxs, loc->mins, size);
10307 for (i = 0;i < 6*4*3;)
10308 for (j = 0;j < 3;j++, i++)
10309 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10311 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10312 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10313 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10316 void R_DrawLocs(void)
10319 cl_locnode_t *loc, *nearestloc;
10321 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10322 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10324 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10325 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10329 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10331 if (decalsystem->decals)
10332 Mem_Free(decalsystem->decals);
10333 memset(decalsystem, 0, sizeof(*decalsystem));
10336 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)
10339 tridecal_t *decals;
10342 // expand or initialize the system
10343 if (decalsystem->maxdecals <= decalsystem->numdecals)
10345 decalsystem_t old = *decalsystem;
10346 qboolean useshortelements;
10347 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10348 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10349 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)));
10350 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10351 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10352 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10353 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10354 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10355 if (decalsystem->numdecals)
10356 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10358 Mem_Free(old.decals);
10359 for (i = 0;i < decalsystem->maxdecals*3;i++)
10360 decalsystem->element3i[i] = i;
10361 if (useshortelements)
10362 for (i = 0;i < decalsystem->maxdecals*3;i++)
10363 decalsystem->element3s[i] = i;
10366 // grab a decal and search for another free slot for the next one
10367 decals = decalsystem->decals;
10368 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10369 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10371 decalsystem->freedecal = i;
10372 if (decalsystem->numdecals <= i)
10373 decalsystem->numdecals = i + 1;
10375 // initialize the decal
10377 decal->triangleindex = triangleindex;
10378 decal->surfaceindex = surfaceindex;
10379 decal->decalsequence = decalsequence;
10380 decal->color4f[0][0] = c0[0];
10381 decal->color4f[0][1] = c0[1];
10382 decal->color4f[0][2] = c0[2];
10383 decal->color4f[0][3] = 1;
10384 decal->color4f[1][0] = c1[0];
10385 decal->color4f[1][1] = c1[1];
10386 decal->color4f[1][2] = c1[2];
10387 decal->color4f[1][3] = 1;
10388 decal->color4f[2][0] = c2[0];
10389 decal->color4f[2][1] = c2[1];
10390 decal->color4f[2][2] = c2[2];
10391 decal->color4f[2][3] = 1;
10392 decal->vertex3f[0][0] = v0[0];
10393 decal->vertex3f[0][1] = v0[1];
10394 decal->vertex3f[0][2] = v0[2];
10395 decal->vertex3f[1][0] = v1[0];
10396 decal->vertex3f[1][1] = v1[1];
10397 decal->vertex3f[1][2] = v1[2];
10398 decal->vertex3f[2][0] = v2[0];
10399 decal->vertex3f[2][1] = v2[1];
10400 decal->vertex3f[2][2] = v2[2];
10401 decal->texcoord2f[0][0] = t0[0];
10402 decal->texcoord2f[0][1] = t0[1];
10403 decal->texcoord2f[1][0] = t1[0];
10404 decal->texcoord2f[1][1] = t1[1];
10405 decal->texcoord2f[2][0] = t2[0];
10406 decal->texcoord2f[2][1] = t2[1];
10407 TriangleNormal(v0, v1, v2, decal->plane);
10408 VectorNormalize(decal->plane);
10409 decal->plane[3] = DotProduct(v0, decal->plane);
10412 extern cvar_t cl_decals_bias;
10413 extern cvar_t cl_decals_models;
10414 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10415 // baseparms, parms, temps
10416 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)
10421 const float *vertex3f;
10422 const float *normal3f;
10424 float points[2][9][3];
10431 e = rsurface.modelelement3i + 3*triangleindex;
10433 vertex3f = rsurface.modelvertex3f;
10434 normal3f = rsurface.modelnormal3f;
10438 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10440 index = 3*e[cornerindex];
10441 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10446 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10448 index = 3*e[cornerindex];
10449 VectorCopy(vertex3f + index, v[cornerindex]);
10454 //TriangleNormal(v[0], v[1], v[2], normal);
10455 //if (DotProduct(normal, localnormal) < 0.0f)
10457 // clip by each of the box planes formed from the projection matrix
10458 // if anything survives, we emit the decal
10459 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]);
10462 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]);
10465 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]);
10468 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]);
10471 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]);
10474 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]);
10477 // some part of the triangle survived, so we have to accept it...
10480 // dynamic always uses the original triangle
10482 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10484 index = 3*e[cornerindex];
10485 VectorCopy(vertex3f + index, v[cornerindex]);
10488 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10490 // convert vertex positions to texcoords
10491 Matrix4x4_Transform(projection, v[cornerindex], temp);
10492 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10493 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10494 // calculate distance fade from the projection origin
10495 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10496 f = bound(0.0f, f, 1.0f);
10497 c[cornerindex][0] = r * f;
10498 c[cornerindex][1] = g * f;
10499 c[cornerindex][2] = b * f;
10500 c[cornerindex][3] = 1.0f;
10501 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10504 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);
10506 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10507 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);
10509 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)
10511 matrix4x4_t projection;
10512 decalsystem_t *decalsystem;
10515 const msurface_t *surface;
10516 const msurface_t *surfaces;
10517 const int *surfacelist;
10518 const texture_t *texture;
10520 int numsurfacelist;
10521 int surfacelistindex;
10524 float localorigin[3];
10525 float localnormal[3];
10526 float localmins[3];
10527 float localmaxs[3];
10530 float planes[6][4];
10533 int bih_triangles_count;
10534 int bih_triangles[256];
10535 int bih_surfaces[256];
10537 decalsystem = &ent->decalsystem;
10538 model = ent->model;
10539 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10541 R_DecalSystem_Reset(&ent->decalsystem);
10545 if (!model->brush.data_leafs && !cl_decals_models.integer)
10547 if (decalsystem->model)
10548 R_DecalSystem_Reset(decalsystem);
10552 if (decalsystem->model != model)
10553 R_DecalSystem_Reset(decalsystem);
10554 decalsystem->model = model;
10556 RSurf_ActiveModelEntity(ent, true, false, false);
10558 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10559 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10560 VectorNormalize(localnormal);
10561 localsize = worldsize*rsurface.inversematrixscale;
10562 localmins[0] = localorigin[0] - localsize;
10563 localmins[1] = localorigin[1] - localsize;
10564 localmins[2] = localorigin[2] - localsize;
10565 localmaxs[0] = localorigin[0] + localsize;
10566 localmaxs[1] = localorigin[1] + localsize;
10567 localmaxs[2] = localorigin[2] + localsize;
10569 //VectorCopy(localnormal, planes[4]);
10570 //VectorVectors(planes[4], planes[2], planes[0]);
10571 AnglesFromVectors(angles, localnormal, NULL, false);
10572 AngleVectors(angles, planes[0], planes[2], planes[4]);
10573 VectorNegate(planes[0], planes[1]);
10574 VectorNegate(planes[2], planes[3]);
10575 VectorNegate(planes[4], planes[5]);
10576 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10577 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10578 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10579 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10580 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10581 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10586 matrix4x4_t forwardprojection;
10587 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10588 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10593 float projectionvector[4][3];
10594 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10595 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10596 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10597 projectionvector[0][0] = planes[0][0] * ilocalsize;
10598 projectionvector[0][1] = planes[1][0] * ilocalsize;
10599 projectionvector[0][2] = planes[2][0] * ilocalsize;
10600 projectionvector[1][0] = planes[0][1] * ilocalsize;
10601 projectionvector[1][1] = planes[1][1] * ilocalsize;
10602 projectionvector[1][2] = planes[2][1] * ilocalsize;
10603 projectionvector[2][0] = planes[0][2] * ilocalsize;
10604 projectionvector[2][1] = planes[1][2] * ilocalsize;
10605 projectionvector[2][2] = planes[2][2] * ilocalsize;
10606 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10607 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10608 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10609 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10613 dynamic = model->surfmesh.isanimated;
10614 numsurfacelist = model->nummodelsurfaces;
10615 surfacelist = model->sortedmodelsurfaces;
10616 surfaces = model->data_surfaces;
10619 bih_triangles_count = -1;
10622 if(model->render_bih.numleafs)
10623 bih = &model->render_bih;
10624 else if(model->collision_bih.numleafs)
10625 bih = &model->collision_bih;
10628 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10629 if(bih_triangles_count == 0)
10631 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10633 if(bih_triangles_count > 0)
10635 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10637 surfaceindex = bih_surfaces[triangleindex];
10638 surface = surfaces + surfaceindex;
10639 texture = surface->texture;
10640 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10642 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10644 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10649 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10651 surfaceindex = surfacelist[surfacelistindex];
10652 surface = surfaces + surfaceindex;
10653 // check cull box first because it rejects more than any other check
10654 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10656 // skip transparent surfaces
10657 texture = surface->texture;
10658 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10660 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10662 numtriangles = surface->num_triangles;
10663 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10664 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10669 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10670 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)
10672 int renderentityindex;
10673 float worldmins[3];
10674 float worldmaxs[3];
10675 entity_render_t *ent;
10677 if (!cl_decals_newsystem.integer)
10680 worldmins[0] = worldorigin[0] - worldsize;
10681 worldmins[1] = worldorigin[1] - worldsize;
10682 worldmins[2] = worldorigin[2] - worldsize;
10683 worldmaxs[0] = worldorigin[0] + worldsize;
10684 worldmaxs[1] = worldorigin[1] + worldsize;
10685 worldmaxs[2] = worldorigin[2] + worldsize;
10687 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10689 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10691 ent = r_refdef.scene.entities[renderentityindex];
10692 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10695 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10699 typedef struct r_decalsystem_splatqueue_s
10701 vec3_t worldorigin;
10702 vec3_t worldnormal;
10708 r_decalsystem_splatqueue_t;
10710 int r_decalsystem_numqueued = 0;
10711 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10713 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)
10715 r_decalsystem_splatqueue_t *queue;
10717 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10720 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10721 VectorCopy(worldorigin, queue->worldorigin);
10722 VectorCopy(worldnormal, queue->worldnormal);
10723 Vector4Set(queue->color, r, g, b, a);
10724 Vector4Set(queue->tcrange, s1, t1, s2, t2);
10725 queue->worldsize = worldsize;
10726 queue->decalsequence = cl.decalsequence++;
10729 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10732 r_decalsystem_splatqueue_t *queue;
10734 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10735 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);
10736 r_decalsystem_numqueued = 0;
10739 extern cvar_t cl_decals_max;
10740 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10743 decalsystem_t *decalsystem = &ent->decalsystem;
10750 if (!decalsystem->numdecals)
10753 if (r_showsurfaces.integer)
10756 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10758 R_DecalSystem_Reset(decalsystem);
10762 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10763 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10765 if (decalsystem->lastupdatetime)
10766 frametime = (cl.time - decalsystem->lastupdatetime);
10769 decalsystem->lastupdatetime = cl.time;
10770 decal = decalsystem->decals;
10771 numdecals = decalsystem->numdecals;
10773 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10775 if (decal->color4f[0][3])
10777 decal->lived += frametime;
10778 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10780 memset(decal, 0, sizeof(*decal));
10781 if (decalsystem->freedecal > i)
10782 decalsystem->freedecal = i;
10786 decal = decalsystem->decals;
10787 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10790 // collapse the array by shuffling the tail decals into the gaps
10793 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10794 decalsystem->freedecal++;
10795 if (decalsystem->freedecal == numdecals)
10797 decal[decalsystem->freedecal] = decal[--numdecals];
10800 decalsystem->numdecals = numdecals;
10802 if (numdecals <= 0)
10804 // if there are no decals left, reset decalsystem
10805 R_DecalSystem_Reset(decalsystem);
10809 extern skinframe_t *decalskinframe;
10810 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10813 decalsystem_t *decalsystem = &ent->decalsystem;
10822 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10825 numdecals = decalsystem->numdecals;
10829 if (r_showsurfaces.integer)
10832 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10834 R_DecalSystem_Reset(decalsystem);
10838 // if the model is static it doesn't matter what value we give for
10839 // wantnormals and wanttangents, so this logic uses only rules applicable
10840 // to a model, knowing that they are meaningless otherwise
10841 if (ent == r_refdef.scene.worldentity)
10842 RSurf_ActiveWorldEntity();
10844 RSurf_ActiveModelEntity(ent, false, false, false);
10846 decalsystem->lastupdatetime = cl.time;
10847 decal = decalsystem->decals;
10849 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10851 // update vertex positions for animated models
10852 v3f = decalsystem->vertex3f;
10853 c4f = decalsystem->color4f;
10854 t2f = decalsystem->texcoord2f;
10855 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10857 if (!decal->color4f[0][3])
10860 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10864 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
10867 // update color values for fading decals
10868 if (decal->lived >= cl_decals_time.value)
10869 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10873 c4f[ 0] = decal->color4f[0][0] * alpha;
10874 c4f[ 1] = decal->color4f[0][1] * alpha;
10875 c4f[ 2] = decal->color4f[0][2] * alpha;
10877 c4f[ 4] = decal->color4f[1][0] * alpha;
10878 c4f[ 5] = decal->color4f[1][1] * alpha;
10879 c4f[ 6] = decal->color4f[1][2] * alpha;
10881 c4f[ 8] = decal->color4f[2][0] * alpha;
10882 c4f[ 9] = decal->color4f[2][1] * alpha;
10883 c4f[10] = decal->color4f[2][2] * alpha;
10886 t2f[0] = decal->texcoord2f[0][0];
10887 t2f[1] = decal->texcoord2f[0][1];
10888 t2f[2] = decal->texcoord2f[1][0];
10889 t2f[3] = decal->texcoord2f[1][1];
10890 t2f[4] = decal->texcoord2f[2][0];
10891 t2f[5] = decal->texcoord2f[2][1];
10893 // update vertex positions for animated models
10894 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10896 e = rsurface.modelelement3i + 3*decal->triangleindex;
10897 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10898 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10899 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10903 VectorCopy(decal->vertex3f[0], v3f);
10904 VectorCopy(decal->vertex3f[1], v3f + 3);
10905 VectorCopy(decal->vertex3f[2], v3f + 6);
10908 if (r_refdef.fogenabled)
10910 alpha = RSurf_FogVertex(v3f);
10911 VectorScale(c4f, alpha, c4f);
10912 alpha = RSurf_FogVertex(v3f + 3);
10913 VectorScale(c4f + 4, alpha, c4f + 4);
10914 alpha = RSurf_FogVertex(v3f + 6);
10915 VectorScale(c4f + 8, alpha, c4f + 8);
10926 r_refdef.stats.drawndecals += numtris;
10928 // now render the decals all at once
10929 // (this assumes they all use one particle font texture!)
10930 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);
10931 // R_Mesh_ResetTextureState();
10932 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10933 GL_DepthMask(false);
10934 GL_DepthRange(0, 1);
10935 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10936 GL_DepthTest(true);
10937 GL_CullFace(GL_NONE);
10938 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10939 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10940 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10944 static void R_DrawModelDecals(void)
10948 // fade faster when there are too many decals
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_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10954 for (i = 0;i < r_refdef.scene.numentities;i++)
10955 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10956 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10958 R_DecalSystem_ApplySplatEntitiesQueue();
10960 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10961 for (i = 0;i < r_refdef.scene.numentities;i++)
10962 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10964 r_refdef.stats.totaldecals += numdecals;
10966 if (r_showsurfaces.integer)
10969 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10971 for (i = 0;i < r_refdef.scene.numentities;i++)
10973 if (!r_refdef.viewcache.entityvisible[i])
10975 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10976 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10980 extern cvar_t mod_collision_bih;
10981 void R_DrawDebugModel(void)
10983 entity_render_t *ent = rsurface.entity;
10984 int i, j, k, l, flagsmask;
10985 const msurface_t *surface;
10986 dp_model_t *model = ent->model;
10989 switch(vid.renderpath)
10991 case RENDERPATH_GL11:
10992 case RENDERPATH_GL13:
10993 case RENDERPATH_GL20:
10995 case RENDERPATH_D3D9:
10996 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10998 case RENDERPATH_D3D10:
10999 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
11001 case RENDERPATH_D3D11:
11002 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
11004 case RENDERPATH_SOFT:
11005 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
11007 case RENDERPATH_GLES2:
11008 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
11012 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11014 // R_Mesh_ResetTextureState();
11015 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11016 GL_DepthRange(0, 1);
11017 GL_DepthTest(!r_showdisabledepthtest.integer);
11018 GL_DepthMask(false);
11019 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11021 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11025 qboolean cullbox = ent == r_refdef.scene.worldentity;
11026 const q3mbrush_t *brush;
11027 const bih_t *bih = &model->collision_bih;
11028 const bih_leaf_t *bihleaf;
11029 float vertex3f[3][3];
11030 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11032 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11034 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11036 switch (bihleaf->type)
11039 brush = model->brush.data_brushes + bihleaf->itemindex;
11040 if (brush->colbrushf && brush->colbrushf->numtriangles)
11042 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);
11043 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11044 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11047 case BIH_COLLISIONTRIANGLE:
11048 triangleindex = bihleaf->itemindex;
11049 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11050 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11051 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11052 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);
11053 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11054 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11056 case BIH_RENDERTRIANGLE:
11057 triangleindex = bihleaf->itemindex;
11058 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11059 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11060 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11061 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);
11062 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11063 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11069 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11071 if (r_showtris.integer || (r_shownormals.value != 0))
11073 if (r_showdisabledepthtest.integer)
11075 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11076 GL_DepthMask(false);
11080 GL_BlendFunc(GL_ONE, GL_ZERO);
11081 GL_DepthMask(true);
11083 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11085 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11087 rsurface.texture = R_GetCurrentTexture(surface->texture);
11088 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11090 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11091 if (r_showtris.value > 0)
11093 if (!rsurface.texture->currentlayers->depthmask)
11094 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11095 else if (ent == r_refdef.scene.worldentity)
11096 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11098 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11099 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11100 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
11102 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
11105 if (r_shownormals.value < 0)
11107 qglBegin(GL_LINES);
11108 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11110 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11111 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11112 qglVertex3f(v[0], v[1], v[2]);
11113 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11114 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11115 qglVertex3f(v[0], v[1], v[2]);
11120 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11122 qglBegin(GL_LINES);
11123 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11125 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11126 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11127 qglVertex3f(v[0], v[1], v[2]);
11128 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11129 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11130 qglVertex3f(v[0], v[1], v[2]);
11134 qglBegin(GL_LINES);
11135 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11137 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11138 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11139 qglVertex3f(v[0], v[1], v[2]);
11140 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11141 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11142 qglVertex3f(v[0], v[1], v[2]);
11146 qglBegin(GL_LINES);
11147 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11149 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11150 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11151 qglVertex3f(v[0], v[1], v[2]);
11152 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11153 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11154 qglVertex3f(v[0], v[1], v[2]);
11161 rsurface.texture = NULL;
11165 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11166 int r_maxsurfacelist = 0;
11167 const msurface_t **r_surfacelist = NULL;
11168 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11170 int i, j, endj, flagsmask;
11171 dp_model_t *model = r_refdef.scene.worldmodel;
11172 msurface_t *surfaces;
11173 unsigned char *update;
11174 int numsurfacelist = 0;
11178 if (r_maxsurfacelist < model->num_surfaces)
11180 r_maxsurfacelist = model->num_surfaces;
11182 Mem_Free((msurface_t**)r_surfacelist);
11183 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11186 RSurf_ActiveWorldEntity();
11188 surfaces = model->data_surfaces;
11189 update = model->brushq1.lightmapupdateflags;
11191 // update light styles on this submodel
11192 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11194 model_brush_lightstyleinfo_t *style;
11195 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11197 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11199 int *list = style->surfacelist;
11200 style->value = r_refdef.scene.lightstylevalue[style->style];
11201 for (j = 0;j < style->numsurfaces;j++)
11202 update[list[j]] = true;
11207 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11211 R_DrawDebugModel();
11212 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11216 rsurface.lightmaptexture = NULL;
11217 rsurface.deluxemaptexture = NULL;
11218 rsurface.uselightmaptexture = false;
11219 rsurface.texture = NULL;
11220 rsurface.rtlight = NULL;
11221 numsurfacelist = 0;
11222 // add visible surfaces to draw list
11223 for (i = 0;i < model->nummodelsurfaces;i++)
11225 j = model->sortedmodelsurfaces[i];
11226 if (r_refdef.viewcache.world_surfacevisible[j])
11227 r_surfacelist[numsurfacelist++] = surfaces + j;
11229 // update lightmaps if needed
11230 if (model->brushq1.firstrender)
11232 model->brushq1.firstrender = false;
11233 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11235 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11239 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11240 if (r_refdef.viewcache.world_surfacevisible[j])
11242 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11244 // don't do anything if there were no surfaces
11245 if (!numsurfacelist)
11247 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11250 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11252 // add to stats if desired
11253 if (r_speeds.integer && !skysurfaces && !depthonly)
11255 r_refdef.stats.world_surfaces += numsurfacelist;
11256 for (j = 0;j < numsurfacelist;j++)
11257 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11260 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11263 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11265 int i, j, endj, flagsmask;
11266 dp_model_t *model = ent->model;
11267 msurface_t *surfaces;
11268 unsigned char *update;
11269 int numsurfacelist = 0;
11273 if (r_maxsurfacelist < model->num_surfaces)
11275 r_maxsurfacelist = model->num_surfaces;
11277 Mem_Free((msurface_t **)r_surfacelist);
11278 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11281 // if the model is static it doesn't matter what value we give for
11282 // wantnormals and wanttangents, so this logic uses only rules applicable
11283 // to a model, knowing that they are meaningless otherwise
11284 if (ent == r_refdef.scene.worldentity)
11285 RSurf_ActiveWorldEntity();
11286 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11287 RSurf_ActiveModelEntity(ent, false, false, false);
11289 RSurf_ActiveModelEntity(ent, true, true, true);
11290 else if (depthonly)
11292 switch (vid.renderpath)
11294 case RENDERPATH_GL20:
11295 case RENDERPATH_D3D9:
11296 case RENDERPATH_D3D10:
11297 case RENDERPATH_D3D11:
11298 case RENDERPATH_SOFT:
11299 case RENDERPATH_GLES2:
11300 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11302 case RENDERPATH_GL13:
11303 case RENDERPATH_GL11:
11304 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11310 switch (vid.renderpath)
11312 case RENDERPATH_GL20:
11313 case RENDERPATH_D3D9:
11314 case RENDERPATH_D3D10:
11315 case RENDERPATH_D3D11:
11316 case RENDERPATH_SOFT:
11317 case RENDERPATH_GLES2:
11318 RSurf_ActiveModelEntity(ent, true, true, false);
11320 case RENDERPATH_GL13:
11321 case RENDERPATH_GL11:
11322 RSurf_ActiveModelEntity(ent, true, false, false);
11327 surfaces = model->data_surfaces;
11328 update = model->brushq1.lightmapupdateflags;
11330 // update light styles
11331 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11333 model_brush_lightstyleinfo_t *style;
11334 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11336 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11338 int *list = style->surfacelist;
11339 style->value = r_refdef.scene.lightstylevalue[style->style];
11340 for (j = 0;j < style->numsurfaces;j++)
11341 update[list[j]] = true;
11346 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11350 R_DrawDebugModel();
11351 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11355 rsurface.lightmaptexture = NULL;
11356 rsurface.deluxemaptexture = NULL;
11357 rsurface.uselightmaptexture = false;
11358 rsurface.texture = NULL;
11359 rsurface.rtlight = NULL;
11360 numsurfacelist = 0;
11361 // add visible surfaces to draw list
11362 for (i = 0;i < model->nummodelsurfaces;i++)
11363 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11364 // don't do anything if there were no surfaces
11365 if (!numsurfacelist)
11367 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11370 // update lightmaps if needed
11374 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11379 R_BuildLightMap(ent, surfaces + j);
11384 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11386 R_BuildLightMap(ent, surfaces + j);
11387 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11389 // add to stats if desired
11390 if (r_speeds.integer && !skysurfaces && !depthonly)
11392 r_refdef.stats.entities_surfaces += numsurfacelist;
11393 for (j = 0;j < numsurfacelist;j++)
11394 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11397 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11400 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11402 static texture_t texture;
11403 static msurface_t surface;
11404 const msurface_t *surfacelist = &surface;
11406 // fake enough texture and surface state to render this geometry
11408 texture.update_lastrenderframe = -1; // regenerate this texture
11409 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11410 texture.currentskinframe = skinframe;
11411 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11412 texture.offsetmapping = OFFSETMAPPING_OFF;
11413 texture.offsetscale = 1;
11414 texture.specularscalemod = 1;
11415 texture.specularpowermod = 1;
11417 surface.texture = &texture;
11418 surface.num_triangles = numtriangles;
11419 surface.num_firsttriangle = firsttriangle;
11420 surface.num_vertices = numvertices;
11421 surface.num_firstvertex = firstvertex;
11424 rsurface.texture = R_GetCurrentTexture(surface.texture);
11425 rsurface.lightmaptexture = NULL;
11426 rsurface.deluxemaptexture = NULL;
11427 rsurface.uselightmaptexture = false;
11428 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11431 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)
11433 static msurface_t surface;
11434 const msurface_t *surfacelist = &surface;
11436 // fake enough texture and surface state to render this geometry
11437 surface.texture = texture;
11438 surface.num_triangles = numtriangles;
11439 surface.num_firsttriangle = firsttriangle;
11440 surface.num_vertices = numvertices;
11441 surface.num_firstvertex = firstvertex;
11444 rsurface.texture = R_GetCurrentTexture(surface.texture);
11445 rsurface.lightmaptexture = NULL;
11446 rsurface.deluxemaptexture = NULL;
11447 rsurface.uselightmaptexture = false;
11448 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);