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 case RENDERPATH_SOFT:
4927 // non-flipped y coordinates
4928 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4929 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
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 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);
5176 void R_EntityMatrix(const matrix4x4_t *matrix)
5178 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5180 gl_modelmatrixchanged = false;
5181 gl_modelmatrix = *matrix;
5182 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5183 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5184 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5185 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5187 switch(vid.renderpath)
5189 case RENDERPATH_D3D9:
5191 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5192 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5195 case RENDERPATH_D3D10:
5196 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5198 case RENDERPATH_D3D11:
5199 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5201 case RENDERPATH_GL13:
5202 case RENDERPATH_GL11:
5203 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5205 case RENDERPATH_SOFT:
5206 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5207 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5209 case RENDERPATH_GL20:
5210 case RENDERPATH_GLES2:
5211 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5212 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5218 void R_ResetViewRendering2D(void)
5220 r_viewport_t viewport;
5223 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5224 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);
5225 R_Mesh_ResetRenderTargets();
5226 R_SetViewport(&viewport);
5227 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5228 GL_Color(1, 1, 1, 1);
5229 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5230 GL_BlendFunc(GL_ONE, GL_ZERO);
5231 GL_ScissorTest(false);
5232 GL_DepthMask(false);
5233 GL_DepthRange(0, 1);
5234 GL_DepthTest(false);
5235 GL_DepthFunc(GL_LEQUAL);
5236 R_EntityMatrix(&identitymatrix);
5237 R_Mesh_ResetTextureState();
5238 GL_PolygonOffset(0, 0);
5239 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5240 switch(vid.renderpath)
5242 case RENDERPATH_GL11:
5243 case RENDERPATH_GL13:
5244 case RENDERPATH_GL20:
5245 case RENDERPATH_GLES2:
5246 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5248 case RENDERPATH_D3D9:
5249 case RENDERPATH_D3D10:
5250 case RENDERPATH_D3D11:
5251 case RENDERPATH_SOFT:
5254 GL_CullFace(GL_NONE);
5257 void R_ResetViewRendering3D(void)
5262 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5263 GL_Color(1, 1, 1, 1);
5264 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5265 GL_BlendFunc(GL_ONE, GL_ZERO);
5266 GL_ScissorTest(true);
5268 GL_DepthRange(0, 1);
5270 GL_DepthFunc(GL_LEQUAL);
5271 R_EntityMatrix(&identitymatrix);
5272 R_Mesh_ResetTextureState();
5273 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5274 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5275 switch(vid.renderpath)
5277 case RENDERPATH_GL11:
5278 case RENDERPATH_GL13:
5279 case RENDERPATH_GL20:
5280 case RENDERPATH_GLES2:
5281 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5283 case RENDERPATH_D3D9:
5284 case RENDERPATH_D3D10:
5285 case RENDERPATH_D3D11:
5286 case RENDERPATH_SOFT:
5289 GL_CullFace(r_refdef.view.cullface_back);
5294 R_RenderView_UpdateViewVectors
5297 static void R_RenderView_UpdateViewVectors(void)
5299 // break apart the view matrix into vectors for various purposes
5300 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5301 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5302 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5303 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5304 // make an inverted copy of the view matrix for tracking sprites
5305 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5308 void R_RenderScene(void);
5309 void R_RenderWaterPlanes(void);
5311 static void R_Water_StartFrame(void)
5314 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5315 r_waterstate_waterplane_t *p;
5317 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5320 switch(vid.renderpath)
5322 case RENDERPATH_GL20:
5323 case RENDERPATH_D3D9:
5324 case RENDERPATH_D3D10:
5325 case RENDERPATH_D3D11:
5326 case RENDERPATH_SOFT:
5327 case RENDERPATH_GLES2:
5329 case RENDERPATH_GL13:
5330 case RENDERPATH_GL11:
5334 // set waterwidth and waterheight to the water resolution that will be
5335 // used (often less than the screen resolution for faster rendering)
5336 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5337 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5339 // calculate desired texture sizes
5340 // can't use water if the card does not support the texture size
5341 if (!r_water.integer || r_showsurfaces.integer)
5342 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5343 else if (vid.support.arb_texture_non_power_of_two)
5345 texturewidth = waterwidth;
5346 textureheight = waterheight;
5347 camerawidth = waterwidth;
5348 cameraheight = waterheight;
5352 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5353 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5354 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5355 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5358 // allocate textures as needed
5359 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5361 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5362 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5364 if (p->texture_refraction)
5365 R_FreeTexture(p->texture_refraction);
5366 p->texture_refraction = NULL;
5367 if (p->texture_reflection)
5368 R_FreeTexture(p->texture_reflection);
5369 p->texture_reflection = NULL;
5370 if (p->texture_camera)
5371 R_FreeTexture(p->texture_camera);
5372 p->texture_camera = NULL;
5374 memset(&r_waterstate, 0, sizeof(r_waterstate));
5375 r_waterstate.texturewidth = texturewidth;
5376 r_waterstate.textureheight = textureheight;
5377 r_waterstate.camerawidth = camerawidth;
5378 r_waterstate.cameraheight = cameraheight;
5381 if (r_waterstate.texturewidth)
5383 r_waterstate.enabled = true;
5385 // when doing a reduced render (HDR) we want to use a smaller area
5386 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5387 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5389 // set up variables that will be used in shader setup
5390 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5391 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5392 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5393 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5396 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5397 r_waterstate.numwaterplanes = 0;
5400 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5402 int triangleindex, planeindex;
5408 r_waterstate_waterplane_t *p;
5409 texture_t *t = R_GetCurrentTexture(surface->texture);
5411 // just use the first triangle with a valid normal for any decisions
5412 VectorClear(normal);
5413 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5415 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5416 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5417 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5418 TriangleNormal(vert[0], vert[1], vert[2], normal);
5419 if (VectorLength2(normal) >= 0.001)
5423 VectorCopy(normal, plane.normal);
5424 VectorNormalize(plane.normal);
5425 plane.dist = DotProduct(vert[0], plane.normal);
5426 PlaneClassify(&plane);
5427 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5429 // skip backfaces (except if nocullface is set)
5430 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5432 VectorNegate(plane.normal, plane.normal);
5434 PlaneClassify(&plane);
5438 // find a matching plane if there is one
5439 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5440 if(p->camera_entity == t->camera_entity)
5441 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5443 if (planeindex >= r_waterstate.maxwaterplanes)
5444 return; // nothing we can do, out of planes
5446 // if this triangle does not fit any known plane rendered this frame, add one
5447 if (planeindex >= r_waterstate.numwaterplanes)
5449 // store the new plane
5450 r_waterstate.numwaterplanes++;
5452 // clear materialflags and pvs
5453 p->materialflags = 0;
5454 p->pvsvalid = false;
5455 p->camera_entity = t->camera_entity;
5456 VectorCopy(surface->mins, p->mins);
5457 VectorCopy(surface->maxs, p->maxs);
5462 p->mins[0] = min(p->mins[0], surface->mins[0]);
5463 p->mins[1] = min(p->mins[1], surface->mins[1]);
5464 p->mins[2] = min(p->mins[2], surface->mins[2]);
5465 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5466 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5467 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5469 // merge this surface's materialflags into the waterplane
5470 p->materialflags |= t->currentmaterialflags;
5471 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5473 // merge this surface's PVS into the waterplane
5474 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5475 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5476 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5478 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5484 static void R_Water_ProcessPlanes(void)
5487 r_refdef_view_t originalview;
5488 r_refdef_view_t myview;
5490 r_waterstate_waterplane_t *p;
5493 originalview = r_refdef.view;
5495 // make sure enough textures are allocated
5496 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5498 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5500 if (!p->texture_refraction)
5501 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);
5502 if (!p->texture_refraction)
5505 else if (p->materialflags & MATERIALFLAG_CAMERA)
5507 if (!p->texture_camera)
5508 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);
5509 if (!p->texture_camera)
5513 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5515 if (!p->texture_reflection)
5516 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);
5517 if (!p->texture_reflection)
5523 r_refdef.view = originalview;
5524 r_refdef.view.showdebug = false;
5525 r_refdef.view.width = r_waterstate.waterwidth;
5526 r_refdef.view.height = r_waterstate.waterheight;
5527 r_refdef.view.useclipplane = true;
5528 myview = r_refdef.view;
5529 r_waterstate.renderingscene = true;
5530 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5532 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5534 r_refdef.view = myview;
5535 if(r_water_scissormode.integer)
5538 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5539 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5542 // render reflected scene and copy into texture
5543 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5544 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5545 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5546 r_refdef.view.clipplane = p->plane;
5548 // reverse the cullface settings for this render
5549 r_refdef.view.cullface_front = GL_FRONT;
5550 r_refdef.view.cullface_back = GL_BACK;
5551 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5553 r_refdef.view.usecustompvs = true;
5555 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5557 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5560 R_ResetViewRendering3D();
5561 R_ClearScreen(r_refdef.fogenabled);
5562 if(r_water_scissormode.integer & 2)
5563 R_View_UpdateWithScissor(myscissor);
5566 if(r_water_scissormode.integer & 1)
5567 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5570 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);
5573 // render the normal view scene and copy into texture
5574 // (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)
5575 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5577 r_refdef.view = myview;
5578 if(r_water_scissormode.integer)
5581 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5582 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5585 r_waterstate.renderingrefraction = true;
5587 r_refdef.view.clipplane = p->plane;
5588 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5589 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5591 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5593 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5594 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5595 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5596 R_RenderView_UpdateViewVectors();
5597 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5599 r_refdef.view.usecustompvs = true;
5600 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);
5604 PlaneClassify(&r_refdef.view.clipplane);
5606 R_ResetViewRendering3D();
5607 R_ClearScreen(r_refdef.fogenabled);
5608 if(r_water_scissormode.integer & 2)
5609 R_View_UpdateWithScissor(myscissor);
5612 if(r_water_scissormode.integer & 1)
5613 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5616 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);
5617 r_waterstate.renderingrefraction = false;
5619 else if (p->materialflags & MATERIALFLAG_CAMERA)
5621 r_refdef.view = myview;
5623 r_refdef.view.clipplane = p->plane;
5624 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5625 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5627 r_refdef.view.width = r_waterstate.camerawidth;
5628 r_refdef.view.height = r_waterstate.cameraheight;
5629 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5630 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5632 if(p->camera_entity)
5634 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5635 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5638 // note: all of the view is used for displaying... so
5639 // there is no use in scissoring
5641 // reverse the cullface settings for this render
5642 r_refdef.view.cullface_front = GL_FRONT;
5643 r_refdef.view.cullface_back = GL_BACK;
5644 // also reverse the view matrix
5645 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
5646 R_RenderView_UpdateViewVectors();
5647 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5649 r_refdef.view.usecustompvs = true;
5650 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);
5653 // camera needs no clipplane
5654 r_refdef.view.useclipplane = false;
5656 PlaneClassify(&r_refdef.view.clipplane);
5658 R_ResetViewRendering3D();
5659 R_ClearScreen(r_refdef.fogenabled);
5663 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);
5664 r_waterstate.renderingrefraction = false;
5668 r_waterstate.renderingscene = false;
5669 r_refdef.view = originalview;
5670 R_ResetViewRendering3D();
5671 R_ClearScreen(r_refdef.fogenabled);
5675 r_refdef.view = originalview;
5676 r_waterstate.renderingscene = false;
5677 Cvar_SetValueQuick(&r_water, 0);
5678 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5682 void R_Bloom_StartFrame(void)
5684 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5685 int viewwidth, viewheight;
5688 if (r_viewscale_fpsscaling.integer)
5690 double actualframetime;
5691 double targetframetime;
5693 actualframetime = r_refdef.lastdrawscreentime;
5694 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5695 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5696 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5697 if (r_viewscale_fpsscaling_stepsize.value > 0)
5698 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5699 viewscalefpsadjusted += adjust;
5700 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5703 viewscalefpsadjusted = 1.0f;
5705 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5707 switch(vid.renderpath)
5709 case RENDERPATH_GL20:
5710 case RENDERPATH_D3D9:
5711 case RENDERPATH_D3D10:
5712 case RENDERPATH_D3D11:
5713 case RENDERPATH_SOFT:
5714 case RENDERPATH_GLES2:
5716 case RENDERPATH_GL13:
5717 case RENDERPATH_GL11:
5721 // set bloomwidth and bloomheight to the bloom resolution that will be
5722 // used (often less than the screen resolution for faster rendering)
5723 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5724 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5725 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5726 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5727 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5729 // calculate desired texture sizes
5730 if (vid.support.arb_texture_non_power_of_two)
5732 screentexturewidth = vid.width;
5733 screentextureheight = vid.height;
5734 bloomtexturewidth = r_bloomstate.bloomwidth;
5735 bloomtextureheight = r_bloomstate.bloomheight;
5739 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
5740 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
5741 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
5742 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
5745 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))
5747 Cvar_SetValueQuick(&r_hdr, 0);
5748 Cvar_SetValueQuick(&r_bloom, 0);
5749 Cvar_SetValueQuick(&r_motionblur, 0);
5750 Cvar_SetValueQuick(&r_damageblur, 0);
5753 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)
5754 screentexturewidth = screentextureheight = 0;
5755 if (!r_hdr.integer && !r_bloom.integer)
5756 bloomtexturewidth = bloomtextureheight = 0;
5758 textype = TEXTYPE_COLORBUFFER;
5759 switch (vid.renderpath)
5761 case RENDERPATH_GL20:
5762 case RENDERPATH_GLES2:
5763 if (vid.support.ext_framebuffer_object)
5765 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5766 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5769 case RENDERPATH_D3D9:
5770 case RENDERPATH_D3D10:
5771 case RENDERPATH_D3D11:
5772 case RENDERPATH_SOFT:
5773 case RENDERPATH_GL13:
5774 case RENDERPATH_GL11:
5778 // allocate textures as needed
5779 if (r_bloomstate.screentexturewidth != screentexturewidth
5780 || r_bloomstate.screentextureheight != screentextureheight
5781 || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5782 || r_bloomstate.bloomtextureheight != bloomtextureheight
5783 || r_bloomstate.texturetype != textype
5784 || r_bloomstate.viewfbo != r_viewfbo.integer)
5786 if (r_bloomstate.texture_bloom)
5787 R_FreeTexture(r_bloomstate.texture_bloom);
5788 r_bloomstate.texture_bloom = NULL;
5789 if (r_bloomstate.texture_screen)
5790 R_FreeTexture(r_bloomstate.texture_screen);
5791 r_bloomstate.texture_screen = NULL;
5792 if (r_bloomstate.fbo_framebuffer)
5793 R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5794 r_bloomstate.fbo_framebuffer = 0;
5795 if (r_bloomstate.texture_framebuffercolor)
5796 R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5797 r_bloomstate.texture_framebuffercolor = NULL;
5798 if (r_bloomstate.texture_framebufferdepth)
5799 R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5800 r_bloomstate.texture_framebufferdepth = NULL;
5801 r_bloomstate.screentexturewidth = screentexturewidth;
5802 r_bloomstate.screentextureheight = screentextureheight;
5803 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5804 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);
5805 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5807 // FIXME: choose depth bits based on a cvar
5808 r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5809 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);
5810 r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5811 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5812 // render depth into one texture and normalmap into the other
5816 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5817 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5818 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
5819 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
5820 Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
5823 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5824 r_bloomstate.bloomtextureheight = bloomtextureheight;
5825 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5826 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);
5827 r_bloomstate.viewfbo = r_viewfbo.integer;
5828 r_bloomstate.texturetype = textype;
5831 // when doing a reduced render (HDR) we want to use a smaller area
5832 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5833 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5834 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5835 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5836 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5838 // set up a texcoord array for the full resolution screen image
5839 // (we have to keep this around to copy back during final render)
5840 r_bloomstate.screentexcoord2f[0] = 0;
5841 r_bloomstate.screentexcoord2f[1] = (float)viewheight / (float)r_bloomstate.screentextureheight;
5842 r_bloomstate.screentexcoord2f[2] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
5843 r_bloomstate.screentexcoord2f[3] = (float)viewheight / (float)r_bloomstate.screentextureheight;
5844 r_bloomstate.screentexcoord2f[4] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
5845 r_bloomstate.screentexcoord2f[5] = 0;
5846 r_bloomstate.screentexcoord2f[6] = 0;
5847 r_bloomstate.screentexcoord2f[7] = 0;
5849 // set up a texcoord array for the reduced resolution bloom image
5850 // (which will be additive blended over the screen image)
5851 r_bloomstate.bloomtexcoord2f[0] = 0;
5852 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5853 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5854 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5855 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5856 r_bloomstate.bloomtexcoord2f[5] = 0;
5857 r_bloomstate.bloomtexcoord2f[6] = 0;
5858 r_bloomstate.bloomtexcoord2f[7] = 0;
5860 switch(vid.renderpath)
5862 case RENDERPATH_GL11:
5863 case RENDERPATH_GL13:
5864 case RENDERPATH_GL20:
5865 case RENDERPATH_SOFT:
5866 case RENDERPATH_GLES2:
5868 case RENDERPATH_D3D9:
5869 case RENDERPATH_D3D10:
5870 case RENDERPATH_D3D11:
5873 for (i = 0;i < 4;i++)
5875 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5876 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5877 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5878 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5884 if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
5886 r_bloomstate.enabled = true;
5887 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
5890 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);
5892 if (r_bloomstate.fbo_framebuffer)
5893 r_refdef.view.clear = true;
5896 void R_Bloom_CopyBloomTexture(float colorscale)
5898 r_refdef.stats.bloom++;
5900 // scale down screen texture to the bloom texture size
5902 R_Mesh_SetMainRenderTargets();
5903 R_SetViewport(&r_bloomstate.viewport);
5904 GL_BlendFunc(GL_ONE, GL_ZERO);
5905 GL_Color(colorscale, colorscale, colorscale, 1);
5906 // 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...
5907 switch(vid.renderpath)
5909 case RENDERPATH_GL11:
5910 case RENDERPATH_GL13:
5911 case RENDERPATH_GL20:
5912 case RENDERPATH_SOFT:
5913 case RENDERPATH_GLES2:
5914 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5916 case RENDERPATH_D3D9:
5917 case RENDERPATH_D3D10:
5918 case RENDERPATH_D3D11:
5919 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5922 // TODO: do boxfilter scale-down in shader?
5923 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5924 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5925 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5927 // we now have a bloom image in the framebuffer
5928 // copy it into the bloom image texture for later processing
5929 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);
5930 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5933 void R_Bloom_CopyHDRTexture(void)
5935 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);
5936 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5939 void R_Bloom_MakeTexture(void)
5942 float xoffset, yoffset, r, brighten;
5944 r_refdef.stats.bloom++;
5946 R_ResetViewRendering2D();
5948 // we have a bloom image in the framebuffer
5950 R_SetViewport(&r_bloomstate.viewport);
5952 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5955 r = bound(0, r_bloom_colorexponent.value / x, 1);
5956 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5958 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5959 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5960 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5961 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5963 // copy the vertically blurred bloom view to a texture
5964 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);
5965 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5968 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5969 brighten = r_bloom_brighten.value;
5970 if (r_bloomstate.hdr)
5971 brighten *= r_hdr_range.value;
5972 brighten = sqrt(brighten);
5974 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5975 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5977 for (dir = 0;dir < 2;dir++)
5979 // blend on at multiple vertical offsets to achieve a vertical blur
5980 // TODO: do offset blends using GLSL
5981 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5982 GL_BlendFunc(GL_ONE, GL_ZERO);
5983 for (x = -range;x <= range;x++)
5985 if (!dir){xoffset = 0;yoffset = x;}
5986 else {xoffset = x;yoffset = 0;}
5987 xoffset /= (float)r_bloomstate.bloomtexturewidth;
5988 yoffset /= (float)r_bloomstate.bloomtextureheight;
5989 // compute a texcoord array with the specified x and y offset
5990 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
5991 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5992 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5993 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5994 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5995 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
5996 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
5997 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
5998 // this r value looks like a 'dot' particle, fading sharply to
5999 // black at the edges
6000 // (probably not realistic but looks good enough)
6001 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6002 //r = brighten/(range*2+1);
6003 r = brighten / (range * 2 + 1);
6005 r *= (1 - x*x/(float)(range*range));
6006 GL_Color(r, r, r, 1);
6007 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6008 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6009 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6010 GL_BlendFunc(GL_ONE, GL_ONE);
6013 // copy the vertically blurred bloom view to a texture
6014 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);
6015 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6019 void R_HDR_RenderBloomTexture(void)
6021 int oldwidth, oldheight;
6022 float oldcolorscale;
6023 qboolean oldwaterstate;
6025 oldwaterstate = r_waterstate.enabled;
6026 oldcolorscale = r_refdef.view.colorscale;
6027 oldwidth = r_refdef.view.width;
6028 oldheight = r_refdef.view.height;
6029 r_refdef.view.width = r_bloomstate.bloomwidth;
6030 r_refdef.view.height = r_bloomstate.bloomheight;
6032 if(r_hdr.integer < 2)
6033 r_waterstate.enabled = false;
6035 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
6036 // TODO: add exposure compensation features
6037 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6039 r_refdef.view.showdebug = false;
6040 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6042 R_ResetViewRendering3D();
6044 R_ClearScreen(r_refdef.fogenabled);
6045 if (r_timereport_active)
6046 R_TimeReport("HDRclear");
6049 if (r_timereport_active)
6050 R_TimeReport("visibility");
6052 // only do secondary renders with HDR if r_hdr is 2 or higher
6053 r_waterstate.numwaterplanes = 0;
6054 if (r_waterstate.enabled)
6055 R_RenderWaterPlanes();
6057 r_refdef.view.showdebug = true;
6059 r_waterstate.numwaterplanes = 0;
6061 R_ResetViewRendering2D();
6063 R_Bloom_CopyHDRTexture();
6064 R_Bloom_MakeTexture();
6066 // restore the view settings
6067 r_waterstate.enabled = oldwaterstate;
6068 r_refdef.view.width = oldwidth;
6069 r_refdef.view.height = oldheight;
6070 r_refdef.view.colorscale = oldcolorscale;
6072 R_ResetViewRendering3D();
6074 R_ClearScreen(r_refdef.fogenabled);
6075 if (r_timereport_active)
6076 R_TimeReport("viewclear");
6079 static void R_BlendView(void)
6081 unsigned int permutation;
6082 float uservecs[4][4];
6084 switch (vid.renderpath)
6086 case RENDERPATH_GL20:
6087 case RENDERPATH_D3D9:
6088 case RENDERPATH_D3D10:
6089 case RENDERPATH_D3D11:
6090 case RENDERPATH_SOFT:
6091 case RENDERPATH_GLES2:
6093 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6094 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6095 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6096 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6097 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6099 if (r_bloomstate.texture_screen)
6101 // make sure the buffer is available
6102 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6104 R_ResetViewRendering2D();
6105 R_Mesh_SetMainRenderTargets();
6107 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6109 // declare variables
6111 static float avgspeed;
6113 speed = VectorLength(cl.movement_velocity);
6115 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6116 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6118 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6119 speed = bound(0, speed, 1);
6120 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6122 // calculate values into a standard alpha
6123 cl.motionbluralpha = 1 - exp(-
6125 (r_motionblur.value * speed / 80)
6127 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6130 max(0.0001, cl.time - cl.oldtime) // fps independent
6133 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6134 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6136 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6138 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6139 GL_Color(1, 1, 1, cl.motionbluralpha);
6140 switch(vid.renderpath)
6142 case RENDERPATH_GL11:
6143 case RENDERPATH_GL13:
6144 case RENDERPATH_GL20:
6145 case RENDERPATH_SOFT:
6146 case RENDERPATH_GLES2:
6147 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6149 case RENDERPATH_D3D9:
6150 case RENDERPATH_D3D10:
6151 case RENDERPATH_D3D11:
6152 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6155 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6156 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6157 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6161 // copy view into the screen texture
6162 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);
6163 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6165 else if (!r_bloomstate.texture_bloom)
6167 // we may still have to do view tint...
6168 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6170 // apply a color tint to the whole view
6171 R_ResetViewRendering2D();
6172 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6173 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6174 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6175 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6176 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6178 break; // no screen processing, no bloom, skip it
6181 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6183 // render simple bloom effect
6184 // copy the screen and shrink it and darken it for the bloom process
6185 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6186 // make the bloom texture
6187 R_Bloom_MakeTexture();
6190 #if _MSC_VER >= 1400
6191 #define sscanf sscanf_s
6193 memset(uservecs, 0, sizeof(uservecs));
6194 if (r_glsl_postprocess_uservec1_enable.integer)
6195 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6196 if (r_glsl_postprocess_uservec2_enable.integer)
6197 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6198 if (r_glsl_postprocess_uservec3_enable.integer)
6199 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6200 if (r_glsl_postprocess_uservec4_enable.integer)
6201 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6203 R_ResetViewRendering2D();
6204 GL_Color(1, 1, 1, 1);
6205 GL_BlendFunc(GL_ONE, GL_ZERO);
6207 switch(vid.renderpath)
6209 case RENDERPATH_GL20:
6210 case RENDERPATH_GLES2:
6211 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6212 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6213 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6214 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6215 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6216 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]);
6217 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6218 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]);
6219 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]);
6220 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]);
6221 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]);
6222 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6223 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6224 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);
6226 case RENDERPATH_D3D9:
6228 // 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...
6229 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6230 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6231 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6232 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6233 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6234 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6235 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6236 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6237 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6238 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6239 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6240 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6241 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6242 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6245 case RENDERPATH_D3D10:
6246 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6248 case RENDERPATH_D3D11:
6249 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6251 case RENDERPATH_SOFT:
6252 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6253 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6254 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6255 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6256 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6257 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6258 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6259 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6260 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6261 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6262 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6263 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6264 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6265 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6270 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6271 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6273 case RENDERPATH_GL13:
6274 case RENDERPATH_GL11:
6275 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6277 // apply a color tint to the whole view
6278 R_ResetViewRendering2D();
6279 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6280 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6281 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6282 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6283 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6289 matrix4x4_t r_waterscrollmatrix;
6291 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6293 if (r_refdef.fog_density)
6295 r_refdef.fogcolor[0] = r_refdef.fog_red;
6296 r_refdef.fogcolor[1] = r_refdef.fog_green;
6297 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6299 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6300 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6301 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6302 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6306 VectorCopy(r_refdef.fogcolor, fogvec);
6307 // color.rgb *= ContrastBoost * SceneBrightness;
6308 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6309 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6310 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6311 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6316 void R_UpdateVariables(void)
6320 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6322 r_refdef.farclip = r_farclip_base.value;
6323 if (r_refdef.scene.worldmodel)
6324 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6325 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6327 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6328 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6329 r_refdef.polygonfactor = 0;
6330 r_refdef.polygonoffset = 0;
6331 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6332 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6334 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6335 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6336 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6337 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6338 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6339 if (FAKELIGHT_ENABLED)
6341 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6343 if (r_showsurfaces.integer)
6345 r_refdef.scene.rtworld = false;
6346 r_refdef.scene.rtworldshadows = false;
6347 r_refdef.scene.rtdlight = false;
6348 r_refdef.scene.rtdlightshadows = false;
6349 r_refdef.lightmapintensity = 0;
6352 if (gamemode == GAME_NEHAHRA)
6354 if (gl_fogenable.integer)
6356 r_refdef.oldgl_fogenable = true;
6357 r_refdef.fog_density = gl_fogdensity.value;
6358 r_refdef.fog_red = gl_fogred.value;
6359 r_refdef.fog_green = gl_foggreen.value;
6360 r_refdef.fog_blue = gl_fogblue.value;
6361 r_refdef.fog_alpha = 1;
6362 r_refdef.fog_start = 0;
6363 r_refdef.fog_end = gl_skyclip.value;
6364 r_refdef.fog_height = 1<<30;
6365 r_refdef.fog_fadedepth = 128;
6367 else if (r_refdef.oldgl_fogenable)
6369 r_refdef.oldgl_fogenable = false;
6370 r_refdef.fog_density = 0;
6371 r_refdef.fog_red = 0;
6372 r_refdef.fog_green = 0;
6373 r_refdef.fog_blue = 0;
6374 r_refdef.fog_alpha = 0;
6375 r_refdef.fog_start = 0;
6376 r_refdef.fog_end = 0;
6377 r_refdef.fog_height = 1<<30;
6378 r_refdef.fog_fadedepth = 128;
6382 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6383 r_refdef.fog_start = max(0, r_refdef.fog_start);
6384 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6386 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6388 if (r_refdef.fog_density && r_drawfog.integer)
6390 r_refdef.fogenabled = true;
6391 // this is the point where the fog reaches 0.9986 alpha, which we
6392 // consider a good enough cutoff point for the texture
6393 // (0.9986 * 256 == 255.6)
6394 if (r_fog_exp2.integer)
6395 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6397 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6398 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6399 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6400 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6401 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6402 R_BuildFogHeightTexture();
6403 // fog color was already set
6404 // update the fog texture
6405 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)
6406 R_BuildFogTexture();
6407 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6408 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6411 r_refdef.fogenabled = false;
6413 switch(vid.renderpath)
6415 case RENDERPATH_GL20:
6416 case RENDERPATH_D3D9:
6417 case RENDERPATH_D3D10:
6418 case RENDERPATH_D3D11:
6419 case RENDERPATH_SOFT:
6420 case RENDERPATH_GLES2:
6421 if(v_glslgamma.integer && !vid_gammatables_trivial)
6423 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6425 // build GLSL gamma texture
6426 #define RAMPWIDTH 256
6427 unsigned short ramp[RAMPWIDTH * 3];
6428 unsigned char rampbgr[RAMPWIDTH][4];
6431 r_texture_gammaramps_serial = vid_gammatables_serial;
6433 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6434 for(i = 0; i < RAMPWIDTH; ++i)
6436 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6437 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6438 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6441 if (r_texture_gammaramps)
6443 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6447 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6453 // remove GLSL gamma texture
6456 case RENDERPATH_GL13:
6457 case RENDERPATH_GL11:
6462 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6463 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6469 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6470 if( scenetype != r_currentscenetype ) {
6471 // store the old scenetype
6472 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6473 r_currentscenetype = scenetype;
6474 // move in the new scene
6475 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6484 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6486 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6487 if( scenetype == r_currentscenetype ) {
6488 return &r_refdef.scene;
6490 return &r_scenes_store[ scenetype ];
6499 int dpsoftrast_test;
6500 void R_RenderView(void)
6502 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6504 dpsoftrast_test = r_test.integer;
6506 if (r_timereport_active)
6507 R_TimeReport("start");
6508 r_textureframe++; // used only by R_GetCurrentTexture
6509 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6511 if(R_CompileShader_CheckStaticParms())
6514 if (!r_drawentities.integer)
6515 r_refdef.scene.numentities = 0;
6517 R_AnimCache_ClearCache();
6518 R_FrameData_NewFrame();
6520 /* adjust for stereo display */
6521 if(R_Stereo_Active())
6523 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);
6524 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6527 if (r_refdef.view.isoverlay)
6529 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6530 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6531 R_TimeReport("depthclear");
6533 r_refdef.view.showdebug = false;
6535 r_waterstate.enabled = false;
6536 r_waterstate.numwaterplanes = 0;
6540 r_refdef.view.matrix = originalmatrix;
6546 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6548 r_refdef.view.matrix = originalmatrix;
6549 return; //Host_Error ("R_RenderView: NULL worldmodel");
6552 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6554 R_RenderView_UpdateViewVectors();
6556 R_Shadow_UpdateWorldLightSelection();
6558 R_Bloom_StartFrame();
6559 R_Water_StartFrame();
6562 if (r_timereport_active)
6563 R_TimeReport("viewsetup");
6565 R_ResetViewRendering3D();
6567 if (r_refdef.view.clear || r_refdef.fogenabled)
6569 R_ClearScreen(r_refdef.fogenabled);
6570 if (r_timereport_active)
6571 R_TimeReport("viewclear");
6573 r_refdef.view.clear = true;
6575 // this produces a bloom texture to be used in R_BlendView() later
6576 if (r_bloomstate.hdr)
6578 R_HDR_RenderBloomTexture();
6579 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6580 r_textureframe++; // used only by R_GetCurrentTexture
6583 r_refdef.view.showdebug = true;
6586 if (r_timereport_active)
6587 R_TimeReport("visibility");
6589 r_waterstate.numwaterplanes = 0;
6590 if (r_waterstate.enabled)
6591 R_RenderWaterPlanes();
6594 r_waterstate.numwaterplanes = 0;
6597 if (r_timereport_active)
6598 R_TimeReport("blendview");
6600 GL_Scissor(0, 0, vid.width, vid.height);
6601 GL_ScissorTest(false);
6603 r_refdef.view.matrix = originalmatrix;
6608 void R_RenderWaterPlanes(void)
6610 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6612 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6613 if (r_timereport_active)
6614 R_TimeReport("waterworld");
6617 // don't let sound skip if going slow
6618 if (r_refdef.scene.extraupdate)
6621 R_DrawModelsAddWaterPlanes();
6622 if (r_timereport_active)
6623 R_TimeReport("watermodels");
6625 if (r_waterstate.numwaterplanes)
6627 R_Water_ProcessPlanes();
6628 if (r_timereport_active)
6629 R_TimeReport("waterscenes");
6633 extern void R_DrawLightningBeams (void);
6634 extern void VM_CL_AddPolygonsToMeshQueue (void);
6635 extern void R_DrawPortals (void);
6636 extern cvar_t cl_locs_show;
6637 static void R_DrawLocs(void);
6638 static void R_DrawEntityBBoxes(void);
6639 static void R_DrawModelDecals(void);
6640 extern void R_DrawModelShadows(void);
6641 extern void R_DrawModelShadowMaps(void);
6642 extern cvar_t cl_decals_newsystem;
6643 extern qboolean r_shadow_usingdeferredprepass;
6644 void R_RenderScene(void)
6646 qboolean shadowmapping = false;
6648 if (r_timereport_active)
6649 R_TimeReport("beginscene");
6651 r_refdef.stats.renders++;
6655 // don't let sound skip if going slow
6656 if (r_refdef.scene.extraupdate)
6659 R_MeshQueue_BeginScene();
6663 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);
6665 if (r_timereport_active)
6666 R_TimeReport("skystartframe");
6668 if (cl.csqc_vidvars.drawworld)
6670 // don't let sound skip if going slow
6671 if (r_refdef.scene.extraupdate)
6674 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6676 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6677 if (r_timereport_active)
6678 R_TimeReport("worldsky");
6681 if (R_DrawBrushModelsSky() && r_timereport_active)
6682 R_TimeReport("bmodelsky");
6684 if (skyrendermasked && skyrenderlater)
6686 // we have to force off the water clipping plane while rendering sky
6690 if (r_timereport_active)
6691 R_TimeReport("sky");
6695 R_AnimCache_CacheVisibleEntities();
6696 if (r_timereport_active)
6697 R_TimeReport("animation");
6699 R_Shadow_PrepareLights();
6700 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6701 R_Shadow_PrepareModelShadows();
6702 if (r_timereport_active)
6703 R_TimeReport("preparelights");
6705 if (R_Shadow_ShadowMappingEnabled())
6706 shadowmapping = true;
6708 if (r_shadow_usingdeferredprepass)
6709 R_Shadow_DrawPrepass();
6711 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6713 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6714 if (r_timereport_active)
6715 R_TimeReport("worlddepth");
6717 if (r_depthfirst.integer >= 2)
6719 R_DrawModelsDepth();
6720 if (r_timereport_active)
6721 R_TimeReport("modeldepth");
6724 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6726 R_DrawModelShadowMaps();
6727 R_ResetViewRendering3D();
6728 // don't let sound skip if going slow
6729 if (r_refdef.scene.extraupdate)
6733 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6735 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6736 if (r_timereport_active)
6737 R_TimeReport("world");
6740 // don't let sound skip if going slow
6741 if (r_refdef.scene.extraupdate)
6745 if (r_timereport_active)
6746 R_TimeReport("models");
6748 // don't let sound skip if going slow
6749 if (r_refdef.scene.extraupdate)
6752 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6754 R_DrawModelShadows();
6755 R_ResetViewRendering3D();
6756 // don't let sound skip if going slow
6757 if (r_refdef.scene.extraupdate)
6761 if (!r_shadow_usingdeferredprepass)
6763 R_Shadow_DrawLights();
6764 if (r_timereport_active)
6765 R_TimeReport("rtlights");
6768 // don't let sound skip if going slow
6769 if (r_refdef.scene.extraupdate)
6772 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6774 R_DrawModelShadows();
6775 R_ResetViewRendering3D();
6776 // don't let sound skip if going slow
6777 if (r_refdef.scene.extraupdate)
6781 if (cl.csqc_vidvars.drawworld)
6783 if (cl_decals_newsystem.integer)
6785 R_DrawModelDecals();
6786 if (r_timereport_active)
6787 R_TimeReport("modeldecals");
6792 if (r_timereport_active)
6793 R_TimeReport("decals");
6797 if (r_timereport_active)
6798 R_TimeReport("particles");
6801 if (r_timereport_active)
6802 R_TimeReport("explosions");
6804 R_DrawLightningBeams();
6805 if (r_timereport_active)
6806 R_TimeReport("lightning");
6809 VM_CL_AddPolygonsToMeshQueue();
6811 if (r_refdef.view.showdebug)
6813 if (cl_locs_show.integer)
6816 if (r_timereport_active)
6817 R_TimeReport("showlocs");
6820 if (r_drawportals.integer)
6823 if (r_timereport_active)
6824 R_TimeReport("portals");
6827 if (r_showbboxes.value > 0)
6829 R_DrawEntityBBoxes();
6830 if (r_timereport_active)
6831 R_TimeReport("bboxes");
6835 R_MeshQueue_RenderTransparent();
6836 if (r_timereport_active)
6837 R_TimeReport("drawtrans");
6839 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))
6841 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6842 if (r_timereport_active)
6843 R_TimeReport("worlddebug");
6844 R_DrawModelsDebug();
6845 if (r_timereport_active)
6846 R_TimeReport("modeldebug");
6849 if (cl.csqc_vidvars.drawworld)
6851 R_Shadow_DrawCoronas();
6852 if (r_timereport_active)
6853 R_TimeReport("coronas");
6858 GL_DepthTest(false);
6859 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6860 GL_Color(1, 1, 1, 1);
6861 qglBegin(GL_POLYGON);
6862 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6863 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6864 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6865 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6867 qglBegin(GL_POLYGON);
6868 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]);
6869 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]);
6870 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]);
6871 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]);
6873 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6877 // don't let sound skip if going slow
6878 if (r_refdef.scene.extraupdate)
6881 R_ResetViewRendering2D();
6884 static const unsigned short bboxelements[36] =
6894 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6897 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6899 RSurf_ActiveWorldEntity();
6901 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6902 GL_DepthMask(false);
6903 GL_DepthRange(0, 1);
6904 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6905 // R_Mesh_ResetTextureState();
6907 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6908 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6909 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6910 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6911 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6912 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6913 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6914 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6915 R_FillColors(color4f, 8, cr, cg, cb, ca);
6916 if (r_refdef.fogenabled)
6918 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6920 f1 = RSurf_FogVertex(v);
6922 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6923 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6924 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6927 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6928 R_Mesh_ResetTextureState();
6929 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6930 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6933 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6937 prvm_edict_t *edict;
6938 prvm_prog_t *prog_save = prog;
6940 // this function draws bounding boxes of server entities
6944 GL_CullFace(GL_NONE);
6945 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6949 for (i = 0;i < numsurfaces;i++)
6951 edict = PRVM_EDICT_NUM(surfacelist[i]);
6952 switch ((int)edict->fields.server->solid)
6954 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
6955 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
6956 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
6957 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6958 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
6959 default: Vector4Set(color, 0, 0, 0, 0.50);break;
6961 color[3] *= r_showbboxes.value;
6962 color[3] = bound(0, color[3], 1);
6963 GL_DepthTest(!r_showdisabledepthtest.integer);
6964 GL_CullFace(r_refdef.view.cullface_front);
6965 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6971 static void R_DrawEntityBBoxes(void)
6974 prvm_edict_t *edict;
6976 prvm_prog_t *prog_save = prog;
6978 // this function draws bounding boxes of server entities
6984 for (i = 0;i < prog->num_edicts;i++)
6986 edict = PRVM_EDICT_NUM(i);
6987 if (edict->priv.server->free)
6989 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6990 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
6992 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
6994 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
6995 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7001 static const int nomodelelement3i[24] =
7013 static const unsigned short nomodelelement3s[24] =
7025 static const float nomodelvertex3f[6*3] =
7035 static const float nomodelcolor4f[6*4] =
7037 0.0f, 0.0f, 0.5f, 1.0f,
7038 0.0f, 0.0f, 0.5f, 1.0f,
7039 0.0f, 0.5f, 0.0f, 1.0f,
7040 0.0f, 0.5f, 0.0f, 1.0f,
7041 0.5f, 0.0f, 0.0f, 1.0f,
7042 0.5f, 0.0f, 0.0f, 1.0f
7045 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7051 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);
7053 // this is only called once per entity so numsurfaces is always 1, and
7054 // surfacelist is always {0}, so this code does not handle batches
7056 if (rsurface.ent_flags & RENDER_ADDITIVE)
7058 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7059 GL_DepthMask(false);
7061 else if (rsurface.colormod[3] < 1)
7063 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7064 GL_DepthMask(false);
7068 GL_BlendFunc(GL_ONE, GL_ZERO);
7071 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7072 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7073 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7074 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7075 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7076 for (i = 0, c = color4f;i < 6;i++, c += 4)
7078 c[0] *= rsurface.colormod[0];
7079 c[1] *= rsurface.colormod[1];
7080 c[2] *= rsurface.colormod[2];
7081 c[3] *= rsurface.colormod[3];
7083 if (r_refdef.fogenabled)
7085 for (i = 0, c = color4f;i < 6;i++, c += 4)
7087 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7089 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7090 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7091 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7094 // R_Mesh_ResetTextureState();
7095 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7096 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7097 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7100 void R_DrawNoModel(entity_render_t *ent)
7103 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7104 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7105 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7107 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7110 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7112 vec3_t right1, right2, diff, normal;
7114 VectorSubtract (org2, org1, normal);
7116 // calculate 'right' vector for start
7117 VectorSubtract (r_refdef.view.origin, org1, diff);
7118 CrossProduct (normal, diff, right1);
7119 VectorNormalize (right1);
7121 // calculate 'right' vector for end
7122 VectorSubtract (r_refdef.view.origin, org2, diff);
7123 CrossProduct (normal, diff, right2);
7124 VectorNormalize (right2);
7126 vert[ 0] = org1[0] + width * right1[0];
7127 vert[ 1] = org1[1] + width * right1[1];
7128 vert[ 2] = org1[2] + width * right1[2];
7129 vert[ 3] = org1[0] - width * right1[0];
7130 vert[ 4] = org1[1] - width * right1[1];
7131 vert[ 5] = org1[2] - width * right1[2];
7132 vert[ 6] = org2[0] - width * right2[0];
7133 vert[ 7] = org2[1] - width * right2[1];
7134 vert[ 8] = org2[2] - width * right2[2];
7135 vert[ 9] = org2[0] + width * right2[0];
7136 vert[10] = org2[1] + width * right2[1];
7137 vert[11] = org2[2] + width * right2[2];
7140 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)
7142 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7143 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7144 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7145 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7146 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7147 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7148 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7149 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7150 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7151 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7152 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7153 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7156 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7161 VectorSet(v, x, y, z);
7162 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7163 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7165 if (i == mesh->numvertices)
7167 if (mesh->numvertices < mesh->maxvertices)
7169 VectorCopy(v, vertex3f);
7170 mesh->numvertices++;
7172 return mesh->numvertices;
7178 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7182 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7183 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7184 e = mesh->element3i + mesh->numtriangles * 3;
7185 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7187 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7188 if (mesh->numtriangles < mesh->maxtriangles)
7193 mesh->numtriangles++;
7195 element[1] = element[2];
7199 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7203 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7204 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7205 e = mesh->element3i + mesh->numtriangles * 3;
7206 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7208 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7209 if (mesh->numtriangles < mesh->maxtriangles)
7214 mesh->numtriangles++;
7216 element[1] = element[2];
7220 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7221 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7223 int planenum, planenum2;
7226 mplane_t *plane, *plane2;
7228 double temppoints[2][256*3];
7229 // figure out how large a bounding box we need to properly compute this brush
7231 for (w = 0;w < numplanes;w++)
7232 maxdist = max(maxdist, fabs(planes[w].dist));
7233 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7234 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7235 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7239 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7240 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7242 if (planenum2 == planenum)
7244 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);
7247 if (tempnumpoints < 3)
7249 // generate elements forming a triangle fan for this polygon
7250 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7254 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)
7256 texturelayer_t *layer;
7257 layer = t->currentlayers + t->currentnumlayers++;
7259 layer->depthmask = depthmask;
7260 layer->blendfunc1 = blendfunc1;
7261 layer->blendfunc2 = blendfunc2;
7262 layer->texture = texture;
7263 layer->texmatrix = *matrix;
7264 layer->color[0] = r;
7265 layer->color[1] = g;
7266 layer->color[2] = b;
7267 layer->color[3] = a;
7270 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7272 if(parms[0] == 0 && parms[1] == 0)
7274 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7275 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7280 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7283 index = parms[2] + r_refdef.scene.time * parms[3];
7284 index -= floor(index);
7285 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7288 case Q3WAVEFUNC_NONE:
7289 case Q3WAVEFUNC_NOISE:
7290 case Q3WAVEFUNC_COUNT:
7293 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7294 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7295 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7296 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7297 case Q3WAVEFUNC_TRIANGLE:
7299 f = index - floor(index);
7310 f = parms[0] + parms[1] * f;
7311 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7312 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7316 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7321 matrix4x4_t matrix, temp;
7322 switch(tcmod->tcmod)
7326 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7327 matrix = r_waterscrollmatrix;
7329 matrix = identitymatrix;
7331 case Q3TCMOD_ENTITYTRANSLATE:
7332 // this is used in Q3 to allow the gamecode to control texcoord
7333 // scrolling on the entity, which is not supported in darkplaces yet.
7334 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7336 case Q3TCMOD_ROTATE:
7337 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7338 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7339 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7342 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7344 case Q3TCMOD_SCROLL:
7345 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7347 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7348 w = (int) tcmod->parms[0];
7349 h = (int) tcmod->parms[1];
7350 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7352 idx = (int) floor(f * w * h);
7353 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7355 case Q3TCMOD_STRETCH:
7356 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7357 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7359 case Q3TCMOD_TRANSFORM:
7360 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7361 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7362 VectorSet(tcmat + 6, 0 , 0 , 1);
7363 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7364 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7366 case Q3TCMOD_TURBULENT:
7367 // this is handled in the RSurf_PrepareVertices function
7368 matrix = identitymatrix;
7372 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7375 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7377 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7378 char name[MAX_QPATH];
7379 skinframe_t *skinframe;
7380 unsigned char pixels[296*194];
7381 strlcpy(cache->name, skinname, sizeof(cache->name));
7382 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7383 if (developer_loading.integer)
7384 Con_Printf("loading %s\n", name);
7385 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7386 if (!skinframe || !skinframe->base)
7389 fs_offset_t filesize;
7391 f = FS_LoadFile(name, tempmempool, true, &filesize);
7394 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7395 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7399 cache->skinframe = skinframe;
7402 texture_t *R_GetCurrentTexture(texture_t *t)
7405 const entity_render_t *ent = rsurface.entity;
7406 dp_model_t *model = ent->model;
7407 q3shaderinfo_layer_tcmod_t *tcmod;
7409 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7410 return t->currentframe;
7411 t->update_lastrenderframe = r_textureframe;
7412 t->update_lastrenderentity = (void *)ent;
7414 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7415 t->camera_entity = ent->entitynumber;
7417 t->camera_entity = 0;
7419 // switch to an alternate material if this is a q1bsp animated material
7421 texture_t *texture = t;
7422 int s = rsurface.ent_skinnum;
7423 if ((unsigned int)s >= (unsigned int)model->numskins)
7425 if (model->skinscenes)
7427 if (model->skinscenes[s].framecount > 1)
7428 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7430 s = model->skinscenes[s].firstframe;
7433 t = t + s * model->num_surfaces;
7436 // use an alternate animation if the entity's frame is not 0,
7437 // and only if the texture has an alternate animation
7438 if (rsurface.ent_alttextures && t->anim_total[1])
7439 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7441 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7443 texture->currentframe = t;
7446 // update currentskinframe to be a qw skin or animation frame
7447 if (rsurface.ent_qwskin >= 0)
7449 i = rsurface.ent_qwskin;
7450 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7452 r_qwskincache_size = cl.maxclients;
7454 Mem_Free(r_qwskincache);
7455 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7457 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7458 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7459 t->currentskinframe = r_qwskincache[i].skinframe;
7460 if (t->currentskinframe == NULL)
7461 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7463 else if (t->numskinframes >= 2)
7464 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7465 if (t->backgroundnumskinframes >= 2)
7466 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7468 t->currentmaterialflags = t->basematerialflags;
7469 t->currentalpha = rsurface.colormod[3];
7470 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7471 t->currentalpha *= r_wateralpha.value;
7472 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7473 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7474 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7475 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7476 if (!(rsurface.ent_flags & RENDER_LIGHT))
7477 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7478 else if (FAKELIGHT_ENABLED)
7480 // no modellight if using fakelight for the map
7482 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7484 // pick a model lighting mode
7485 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7486 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7488 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7490 if (rsurface.ent_flags & RENDER_ADDITIVE)
7491 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7492 else if (t->currentalpha < 1)
7493 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7494 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7495 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7496 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7497 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7498 if (t->backgroundnumskinframes)
7499 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7500 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7502 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7503 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7506 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7507 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7508 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7510 // there is no tcmod
7511 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7513 t->currenttexmatrix = r_waterscrollmatrix;
7514 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7516 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7518 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7519 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7522 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7523 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7524 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7525 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7527 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7528 if (t->currentskinframe->qpixels)
7529 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7530 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7531 if (!t->basetexture)
7532 t->basetexture = r_texture_notexture;
7533 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7534 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7535 t->nmaptexture = t->currentskinframe->nmap;
7536 if (!t->nmaptexture)
7537 t->nmaptexture = r_texture_blanknormalmap;
7538 t->glosstexture = r_texture_black;
7539 t->glowtexture = t->currentskinframe->glow;
7540 t->fogtexture = t->currentskinframe->fog;
7541 t->reflectmasktexture = t->currentskinframe->reflect;
7542 if (t->backgroundnumskinframes)
7544 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7545 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7546 t->backgroundglosstexture = r_texture_black;
7547 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7548 if (!t->backgroundnmaptexture)
7549 t->backgroundnmaptexture = r_texture_blanknormalmap;
7553 t->backgroundbasetexture = r_texture_white;
7554 t->backgroundnmaptexture = r_texture_blanknormalmap;
7555 t->backgroundglosstexture = r_texture_black;
7556 t->backgroundglowtexture = NULL;
7558 t->specularpower = r_shadow_glossexponent.value;
7559 // TODO: store reference values for these in the texture?
7560 t->specularscale = 0;
7561 if (r_shadow_gloss.integer > 0)
7563 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7565 if (r_shadow_glossintensity.value > 0)
7567 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7568 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7569 t->specularscale = r_shadow_glossintensity.value;
7572 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7574 t->glosstexture = r_texture_white;
7575 t->backgroundglosstexture = r_texture_white;
7576 t->specularscale = r_shadow_gloss2intensity.value;
7577 t->specularpower = r_shadow_gloss2exponent.value;
7580 t->specularscale *= t->specularscalemod;
7581 t->specularpower *= t->specularpowermod;
7583 // lightmaps mode looks bad with dlights using actual texturing, so turn
7584 // off the colormap and glossmap, but leave the normalmap on as it still
7585 // accurately represents the shading involved
7586 if (gl_lightmaps.integer)
7588 t->basetexture = r_texture_grey128;
7589 t->pantstexture = r_texture_black;
7590 t->shirttexture = r_texture_black;
7591 t->nmaptexture = r_texture_blanknormalmap;
7592 t->glosstexture = r_texture_black;
7593 t->glowtexture = NULL;
7594 t->fogtexture = NULL;
7595 t->reflectmasktexture = NULL;
7596 t->backgroundbasetexture = NULL;
7597 t->backgroundnmaptexture = r_texture_blanknormalmap;
7598 t->backgroundglosstexture = r_texture_black;
7599 t->backgroundglowtexture = NULL;
7600 t->specularscale = 0;
7601 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7604 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7605 VectorClear(t->dlightcolor);
7606 t->currentnumlayers = 0;
7607 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7609 int blendfunc1, blendfunc2;
7611 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7613 blendfunc1 = GL_SRC_ALPHA;
7614 blendfunc2 = GL_ONE;
7616 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7618 blendfunc1 = GL_SRC_ALPHA;
7619 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7621 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7623 blendfunc1 = t->customblendfunc[0];
7624 blendfunc2 = t->customblendfunc[1];
7628 blendfunc1 = GL_ONE;
7629 blendfunc2 = GL_ZERO;
7631 // don't colormod evilblend textures
7632 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7633 VectorSet(t->lightmapcolor, 1, 1, 1);
7634 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7635 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7637 // fullbright is not affected by r_refdef.lightmapintensity
7638 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]);
7639 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7640 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]);
7641 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7642 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]);
7646 vec3_t ambientcolor;
7648 // set the color tint used for lights affecting this surface
7649 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7651 // q3bsp has no lightmap updates, so the lightstylevalue that
7652 // would normally be baked into the lightmap must be
7653 // applied to the color
7654 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7655 if (model->type == mod_brushq3)
7656 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7657 colorscale *= r_refdef.lightmapintensity;
7658 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7659 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7660 // basic lit geometry
7661 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]);
7662 // add pants/shirt if needed
7663 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7664 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]);
7665 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7666 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]);
7667 // now add ambient passes if needed
7668 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7670 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]);
7671 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7672 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]);
7673 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7674 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]);
7677 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7678 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]);
7679 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7681 // if this is opaque use alpha blend which will darken the earlier
7684 // if this is an alpha blended material, all the earlier passes
7685 // were darkened by fog already, so we only need to add the fog
7686 // color ontop through the fog mask texture
7688 // if this is an additive blended material, all the earlier passes
7689 // were darkened by fog already, and we should not add fog color
7690 // (because the background was not darkened, there is no fog color
7691 // that was lost behind it).
7692 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]);
7696 return t->currentframe;
7699 rsurfacestate_t rsurface;
7701 void RSurf_ActiveWorldEntity(void)
7703 dp_model_t *model = r_refdef.scene.worldmodel;
7704 //if (rsurface.entity == r_refdef.scene.worldentity)
7706 rsurface.entity = r_refdef.scene.worldentity;
7707 rsurface.skeleton = NULL;
7708 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7709 rsurface.ent_skinnum = 0;
7710 rsurface.ent_qwskin = -1;
7711 rsurface.ent_shadertime = 0;
7712 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7713 rsurface.matrix = identitymatrix;
7714 rsurface.inversematrix = identitymatrix;
7715 rsurface.matrixscale = 1;
7716 rsurface.inversematrixscale = 1;
7717 R_EntityMatrix(&identitymatrix);
7718 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7719 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7720 rsurface.fograngerecip = r_refdef.fograngerecip;
7721 rsurface.fogheightfade = r_refdef.fogheightfade;
7722 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7723 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7724 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7725 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7726 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7727 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7728 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7729 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7730 rsurface.colormod[3] = 1;
7731 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);
7732 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7733 rsurface.frameblend[0].lerp = 1;
7734 rsurface.ent_alttextures = false;
7735 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7736 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7737 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7738 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7739 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7740 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7741 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7742 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7743 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7744 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7745 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7746 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7747 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7748 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7749 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7750 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7751 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7752 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7753 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7754 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7755 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7756 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7757 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7758 rsurface.modelelement3i = model->surfmesh.data_element3i;
7759 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7760 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7761 rsurface.modelelement3s = model->surfmesh.data_element3s;
7762 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7763 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7764 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7765 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7766 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7767 rsurface.modelsurfaces = model->data_surfaces;
7768 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7769 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7770 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7771 rsurface.modelgeneratedvertex = false;
7772 rsurface.batchgeneratedvertex = false;
7773 rsurface.batchfirstvertex = 0;
7774 rsurface.batchnumvertices = 0;
7775 rsurface.batchfirsttriangle = 0;
7776 rsurface.batchnumtriangles = 0;
7777 rsurface.batchvertex3f = NULL;
7778 rsurface.batchvertex3f_vertexbuffer = NULL;
7779 rsurface.batchvertex3f_bufferoffset = 0;
7780 rsurface.batchsvector3f = NULL;
7781 rsurface.batchsvector3f_vertexbuffer = NULL;
7782 rsurface.batchsvector3f_bufferoffset = 0;
7783 rsurface.batchtvector3f = NULL;
7784 rsurface.batchtvector3f_vertexbuffer = NULL;
7785 rsurface.batchtvector3f_bufferoffset = 0;
7786 rsurface.batchnormal3f = NULL;
7787 rsurface.batchnormal3f_vertexbuffer = NULL;
7788 rsurface.batchnormal3f_bufferoffset = 0;
7789 rsurface.batchlightmapcolor4f = NULL;
7790 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7791 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7792 rsurface.batchtexcoordtexture2f = NULL;
7793 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7794 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7795 rsurface.batchtexcoordlightmap2f = NULL;
7796 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7797 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7798 rsurface.batchvertexmesh = NULL;
7799 rsurface.batchvertexmeshbuffer = NULL;
7800 rsurface.batchvertex3fbuffer = NULL;
7801 rsurface.batchelement3i = NULL;
7802 rsurface.batchelement3i_indexbuffer = NULL;
7803 rsurface.batchelement3i_bufferoffset = 0;
7804 rsurface.batchelement3s = NULL;
7805 rsurface.batchelement3s_indexbuffer = NULL;
7806 rsurface.batchelement3s_bufferoffset = 0;
7807 rsurface.passcolor4f = NULL;
7808 rsurface.passcolor4f_vertexbuffer = NULL;
7809 rsurface.passcolor4f_bufferoffset = 0;
7812 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7814 dp_model_t *model = ent->model;
7815 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7817 rsurface.entity = (entity_render_t *)ent;
7818 rsurface.skeleton = ent->skeleton;
7819 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7820 rsurface.ent_skinnum = ent->skinnum;
7821 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;
7822 rsurface.ent_shadertime = ent->shadertime;
7823 rsurface.ent_flags = ent->flags;
7824 rsurface.matrix = ent->matrix;
7825 rsurface.inversematrix = ent->inversematrix;
7826 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7827 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7828 R_EntityMatrix(&rsurface.matrix);
7829 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7830 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7831 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7832 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7833 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7834 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7835 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7836 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7837 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7838 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7839 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7840 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7841 rsurface.colormod[3] = ent->alpha;
7842 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7843 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7844 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7845 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7846 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7847 if (ent->model->brush.submodel && !prepass)
7849 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7850 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7852 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7854 if (ent->animcache_vertex3f)
7856 rsurface.modelvertex3f = ent->animcache_vertex3f;
7857 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7858 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7859 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7860 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7861 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7862 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7864 else if (wanttangents)
7866 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7867 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7868 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7869 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7870 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7871 rsurface.modelvertexmesh = NULL;
7872 rsurface.modelvertexmeshbuffer = NULL;
7873 rsurface.modelvertex3fbuffer = NULL;
7875 else if (wantnormals)
7877 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7878 rsurface.modelsvector3f = NULL;
7879 rsurface.modeltvector3f = NULL;
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, NULL, NULL);
7882 rsurface.modelvertexmesh = NULL;
7883 rsurface.modelvertexmeshbuffer = NULL;
7884 rsurface.modelvertex3fbuffer = NULL;
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 = NULL;
7892 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7893 rsurface.modelvertexmesh = NULL;
7894 rsurface.modelvertexmeshbuffer = NULL;
7895 rsurface.modelvertex3fbuffer = NULL;
7897 rsurface.modelvertex3f_vertexbuffer = 0;
7898 rsurface.modelvertex3f_bufferoffset = 0;
7899 rsurface.modelsvector3f_vertexbuffer = 0;
7900 rsurface.modelsvector3f_bufferoffset = 0;
7901 rsurface.modeltvector3f_vertexbuffer = 0;
7902 rsurface.modeltvector3f_bufferoffset = 0;
7903 rsurface.modelnormal3f_vertexbuffer = 0;
7904 rsurface.modelnormal3f_bufferoffset = 0;
7905 rsurface.modelgeneratedvertex = true;
7909 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7910 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7911 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7912 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7913 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7914 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7915 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7916 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7917 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7918 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7919 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7920 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7921 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7922 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7923 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7924 rsurface.modelgeneratedvertex = false;
7926 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7927 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7928 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7929 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7930 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7931 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7932 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7933 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7934 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7935 rsurface.modelelement3i = model->surfmesh.data_element3i;
7936 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7937 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7938 rsurface.modelelement3s = model->surfmesh.data_element3s;
7939 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7940 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7941 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7942 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7943 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7944 rsurface.modelsurfaces = model->data_surfaces;
7945 rsurface.batchgeneratedvertex = false;
7946 rsurface.batchfirstvertex = 0;
7947 rsurface.batchnumvertices = 0;
7948 rsurface.batchfirsttriangle = 0;
7949 rsurface.batchnumtriangles = 0;
7950 rsurface.batchvertex3f = NULL;
7951 rsurface.batchvertex3f_vertexbuffer = NULL;
7952 rsurface.batchvertex3f_bufferoffset = 0;
7953 rsurface.batchsvector3f = NULL;
7954 rsurface.batchsvector3f_vertexbuffer = NULL;
7955 rsurface.batchsvector3f_bufferoffset = 0;
7956 rsurface.batchtvector3f = NULL;
7957 rsurface.batchtvector3f_vertexbuffer = NULL;
7958 rsurface.batchtvector3f_bufferoffset = 0;
7959 rsurface.batchnormal3f = NULL;
7960 rsurface.batchnormal3f_vertexbuffer = NULL;
7961 rsurface.batchnormal3f_bufferoffset = 0;
7962 rsurface.batchlightmapcolor4f = NULL;
7963 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7964 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7965 rsurface.batchtexcoordtexture2f = NULL;
7966 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7967 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7968 rsurface.batchtexcoordlightmap2f = NULL;
7969 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7970 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7971 rsurface.batchvertexmesh = NULL;
7972 rsurface.batchvertexmeshbuffer = NULL;
7973 rsurface.batchvertex3fbuffer = NULL;
7974 rsurface.batchelement3i = NULL;
7975 rsurface.batchelement3i_indexbuffer = NULL;
7976 rsurface.batchelement3i_bufferoffset = 0;
7977 rsurface.batchelement3s = NULL;
7978 rsurface.batchelement3s_indexbuffer = NULL;
7979 rsurface.batchelement3s_bufferoffset = 0;
7980 rsurface.passcolor4f = NULL;
7981 rsurface.passcolor4f_vertexbuffer = NULL;
7982 rsurface.passcolor4f_bufferoffset = 0;
7985 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)
7987 rsurface.entity = r_refdef.scene.worldentity;
7988 rsurface.skeleton = NULL;
7989 rsurface.ent_skinnum = 0;
7990 rsurface.ent_qwskin = -1;
7991 rsurface.ent_shadertime = shadertime;
7992 rsurface.ent_flags = entflags;
7993 rsurface.modelnumvertices = numvertices;
7994 rsurface.modelnumtriangles = numtriangles;
7995 rsurface.matrix = *matrix;
7996 rsurface.inversematrix = *inversematrix;
7997 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7998 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7999 R_EntityMatrix(&rsurface.matrix);
8000 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8001 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8002 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8003 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8004 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8005 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8006 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8007 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8008 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8009 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8010 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8011 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8012 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);
8013 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8014 rsurface.frameblend[0].lerp = 1;
8015 rsurface.ent_alttextures = false;
8016 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8017 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8020 rsurface.modelvertex3f = (float *)vertex3f;
8021 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8022 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8023 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8025 else if (wantnormals)
8027 rsurface.modelvertex3f = (float *)vertex3f;
8028 rsurface.modelsvector3f = NULL;
8029 rsurface.modeltvector3f = NULL;
8030 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8034 rsurface.modelvertex3f = (float *)vertex3f;
8035 rsurface.modelsvector3f = NULL;
8036 rsurface.modeltvector3f = NULL;
8037 rsurface.modelnormal3f = NULL;
8039 rsurface.modelvertexmesh = NULL;
8040 rsurface.modelvertexmeshbuffer = NULL;
8041 rsurface.modelvertex3fbuffer = NULL;
8042 rsurface.modelvertex3f_vertexbuffer = 0;
8043 rsurface.modelvertex3f_bufferoffset = 0;
8044 rsurface.modelsvector3f_vertexbuffer = 0;
8045 rsurface.modelsvector3f_bufferoffset = 0;
8046 rsurface.modeltvector3f_vertexbuffer = 0;
8047 rsurface.modeltvector3f_bufferoffset = 0;
8048 rsurface.modelnormal3f_vertexbuffer = 0;
8049 rsurface.modelnormal3f_bufferoffset = 0;
8050 rsurface.modelgeneratedvertex = true;
8051 rsurface.modellightmapcolor4f = (float *)color4f;
8052 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8053 rsurface.modellightmapcolor4f_bufferoffset = 0;
8054 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8055 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8056 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8057 rsurface.modeltexcoordlightmap2f = NULL;
8058 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8059 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8060 rsurface.modelelement3i = (int *)element3i;
8061 rsurface.modelelement3i_indexbuffer = NULL;
8062 rsurface.modelelement3i_bufferoffset = 0;
8063 rsurface.modelelement3s = (unsigned short *)element3s;
8064 rsurface.modelelement3s_indexbuffer = NULL;
8065 rsurface.modelelement3s_bufferoffset = 0;
8066 rsurface.modellightmapoffsets = NULL;
8067 rsurface.modelsurfaces = NULL;
8068 rsurface.batchgeneratedvertex = false;
8069 rsurface.batchfirstvertex = 0;
8070 rsurface.batchnumvertices = 0;
8071 rsurface.batchfirsttriangle = 0;
8072 rsurface.batchnumtriangles = 0;
8073 rsurface.batchvertex3f = NULL;
8074 rsurface.batchvertex3f_vertexbuffer = NULL;
8075 rsurface.batchvertex3f_bufferoffset = 0;
8076 rsurface.batchsvector3f = NULL;
8077 rsurface.batchsvector3f_vertexbuffer = NULL;
8078 rsurface.batchsvector3f_bufferoffset = 0;
8079 rsurface.batchtvector3f = NULL;
8080 rsurface.batchtvector3f_vertexbuffer = NULL;
8081 rsurface.batchtvector3f_bufferoffset = 0;
8082 rsurface.batchnormal3f = NULL;
8083 rsurface.batchnormal3f_vertexbuffer = NULL;
8084 rsurface.batchnormal3f_bufferoffset = 0;
8085 rsurface.batchlightmapcolor4f = NULL;
8086 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8087 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8088 rsurface.batchtexcoordtexture2f = NULL;
8089 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8090 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8091 rsurface.batchtexcoordlightmap2f = NULL;
8092 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8093 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8094 rsurface.batchvertexmesh = NULL;
8095 rsurface.batchvertexmeshbuffer = NULL;
8096 rsurface.batchvertex3fbuffer = NULL;
8097 rsurface.batchelement3i = NULL;
8098 rsurface.batchelement3i_indexbuffer = NULL;
8099 rsurface.batchelement3i_bufferoffset = 0;
8100 rsurface.batchelement3s = NULL;
8101 rsurface.batchelement3s_indexbuffer = NULL;
8102 rsurface.batchelement3s_bufferoffset = 0;
8103 rsurface.passcolor4f = NULL;
8104 rsurface.passcolor4f_vertexbuffer = NULL;
8105 rsurface.passcolor4f_bufferoffset = 0;
8107 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8109 if ((wantnormals || wanttangents) && !normal3f)
8111 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8112 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8114 if (wanttangents && !svector3f)
8116 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8117 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8118 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8123 float RSurf_FogPoint(const float *v)
8125 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8126 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8127 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8128 float FogHeightFade = r_refdef.fogheightfade;
8130 unsigned int fogmasktableindex;
8131 if (r_refdef.fogplaneviewabove)
8132 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8134 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8135 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8136 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8139 float RSurf_FogVertex(const float *v)
8141 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8142 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8143 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8144 float FogHeightFade = rsurface.fogheightfade;
8146 unsigned int fogmasktableindex;
8147 if (r_refdef.fogplaneviewabove)
8148 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8150 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8151 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8152 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8155 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8158 for (i = 0;i < numelements;i++)
8159 outelement3i[i] = inelement3i[i] + adjust;
8162 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8163 extern cvar_t gl_vbo;
8164 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8172 int surfacefirsttriangle;
8173 int surfacenumtriangles;
8174 int surfacefirstvertex;
8175 int surfaceendvertex;
8176 int surfacenumvertices;
8177 int batchnumvertices;
8178 int batchnumtriangles;
8182 qboolean dynamicvertex;
8186 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8188 q3shaderinfo_deform_t *deform;
8189 const msurface_t *surface, *firstsurface;
8190 r_vertexmesh_t *vertexmesh;
8191 if (!texturenumsurfaces)
8193 // find vertex range of this surface batch
8195 firstsurface = texturesurfacelist[0];
8196 firsttriangle = firstsurface->num_firsttriangle;
8197 batchnumvertices = 0;
8198 batchnumtriangles = 0;
8199 firstvertex = endvertex = firstsurface->num_firstvertex;
8200 for (i = 0;i < texturenumsurfaces;i++)
8202 surface = texturesurfacelist[i];
8203 if (surface != firstsurface + i)
8205 surfacefirstvertex = surface->num_firstvertex;
8206 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8207 surfacenumvertices = surface->num_vertices;
8208 surfacenumtriangles = surface->num_triangles;
8209 if (firstvertex > surfacefirstvertex)
8210 firstvertex = surfacefirstvertex;
8211 if (endvertex < surfaceendvertex)
8212 endvertex = surfaceendvertex;
8213 batchnumvertices += surfacenumvertices;
8214 batchnumtriangles += surfacenumtriangles;
8217 // we now know the vertex range used, and if there are any gaps in it
8218 rsurface.batchfirstvertex = firstvertex;
8219 rsurface.batchnumvertices = endvertex - firstvertex;
8220 rsurface.batchfirsttriangle = firsttriangle;
8221 rsurface.batchnumtriangles = batchnumtriangles;
8223 // this variable holds flags for which properties have been updated that
8224 // may require regenerating vertexmesh array...
8227 // check if any dynamic vertex processing must occur
8228 dynamicvertex = false;
8230 // if there is a chance of animated vertex colors, it's a dynamic batch
8231 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8233 dynamicvertex = true;
8234 batchneed |= BATCHNEED_NOGAPS;
8235 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8238 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8240 switch (deform->deform)
8243 case Q3DEFORM_PROJECTIONSHADOW:
8244 case Q3DEFORM_TEXT0:
8245 case Q3DEFORM_TEXT1:
8246 case Q3DEFORM_TEXT2:
8247 case Q3DEFORM_TEXT3:
8248 case Q3DEFORM_TEXT4:
8249 case Q3DEFORM_TEXT5:
8250 case Q3DEFORM_TEXT6:
8251 case Q3DEFORM_TEXT7:
8254 case Q3DEFORM_AUTOSPRITE:
8255 dynamicvertex = true;
8256 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8257 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8259 case Q3DEFORM_AUTOSPRITE2:
8260 dynamicvertex = true;
8261 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8262 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8264 case Q3DEFORM_NORMAL:
8265 dynamicvertex = true;
8266 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8267 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8270 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8271 break; // if wavefunc is a nop, ignore this transform
8272 dynamicvertex = true;
8273 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8274 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8276 case Q3DEFORM_BULGE:
8277 dynamicvertex = true;
8278 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8279 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8282 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8283 break; // if wavefunc is a nop, ignore this transform
8284 dynamicvertex = true;
8285 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8286 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8290 switch(rsurface.texture->tcgen.tcgen)
8293 case Q3TCGEN_TEXTURE:
8295 case Q3TCGEN_LIGHTMAP:
8296 dynamicvertex = true;
8297 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8298 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8300 case Q3TCGEN_VECTOR:
8301 dynamicvertex = true;
8302 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8303 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8305 case Q3TCGEN_ENVIRONMENT:
8306 dynamicvertex = true;
8307 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8308 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8311 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8313 dynamicvertex = true;
8314 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8315 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8318 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8320 dynamicvertex = true;
8321 batchneed |= BATCHNEED_NOGAPS;
8322 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8325 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8327 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8328 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8329 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8330 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8331 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8332 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8333 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8336 // when the model data has no vertex buffer (dynamic mesh), we need to
8338 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8339 batchneed |= BATCHNEED_NOGAPS;
8341 // if needsupdate, we have to do a dynamic vertex batch for sure
8342 if (needsupdate & batchneed)
8343 dynamicvertex = true;
8345 // see if we need to build vertexmesh from arrays
8346 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8347 dynamicvertex = true;
8349 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8350 // also some drivers strongly dislike firstvertex
8351 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8352 dynamicvertex = true;
8354 rsurface.batchvertex3f = rsurface.modelvertex3f;
8355 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8356 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8357 rsurface.batchsvector3f = rsurface.modelsvector3f;
8358 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8359 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8360 rsurface.batchtvector3f = rsurface.modeltvector3f;
8361 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8362 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8363 rsurface.batchnormal3f = rsurface.modelnormal3f;
8364 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8365 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8366 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8367 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8368 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8369 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8370 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8371 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8372 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8373 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8374 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8375 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8376 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8377 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8378 rsurface.batchelement3i = rsurface.modelelement3i;
8379 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8380 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8381 rsurface.batchelement3s = rsurface.modelelement3s;
8382 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8383 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8385 // if any dynamic vertex processing has to occur in software, we copy the
8386 // entire surface list together before processing to rebase the vertices
8387 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8389 // if any gaps exist and we do not have a static vertex buffer, we have to
8390 // copy the surface list together to avoid wasting upload bandwidth on the
8391 // vertices in the gaps.
8393 // if gaps exist and we have a static vertex buffer, we still have to
8394 // combine the index buffer ranges into one dynamic index buffer.
8396 // in all cases we end up with data that can be drawn in one call.
8400 // static vertex data, just set pointers...
8401 rsurface.batchgeneratedvertex = false;
8402 // if there are gaps, we want to build a combined index buffer,
8403 // otherwise use the original static buffer with an appropriate offset
8406 // build a new triangle elements array for this batch
8407 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8408 rsurface.batchfirsttriangle = 0;
8410 for (i = 0;i < texturenumsurfaces;i++)
8412 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8413 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8414 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8415 numtriangles += surfacenumtriangles;
8417 rsurface.batchelement3i_indexbuffer = NULL;
8418 rsurface.batchelement3i_bufferoffset = 0;
8419 rsurface.batchelement3s = NULL;
8420 rsurface.batchelement3s_indexbuffer = NULL;
8421 rsurface.batchelement3s_bufferoffset = 0;
8422 if (endvertex <= 65536)
8424 // make a 16bit (unsigned short) index array if possible
8425 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8426 for (i = 0;i < numtriangles*3;i++)
8427 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8433 // something needs software processing, do it for real...
8434 // we only directly handle separate array data in this case and then
8435 // generate interleaved data if needed...
8436 rsurface.batchgeneratedvertex = true;
8438 // now copy the vertex data into a combined array and make an index array
8439 // (this is what Quake3 does all the time)
8440 //if (gaps || rsurface.batchfirstvertex)
8442 rsurface.batchvertex3fbuffer = NULL;
8443 rsurface.batchvertexmesh = NULL;
8444 rsurface.batchvertexmeshbuffer = NULL;
8445 rsurface.batchvertex3f = NULL;
8446 rsurface.batchvertex3f_vertexbuffer = NULL;
8447 rsurface.batchvertex3f_bufferoffset = 0;
8448 rsurface.batchsvector3f = NULL;
8449 rsurface.batchsvector3f_vertexbuffer = NULL;
8450 rsurface.batchsvector3f_bufferoffset = 0;
8451 rsurface.batchtvector3f = NULL;
8452 rsurface.batchtvector3f_vertexbuffer = NULL;
8453 rsurface.batchtvector3f_bufferoffset = 0;
8454 rsurface.batchnormal3f = NULL;
8455 rsurface.batchnormal3f_vertexbuffer = NULL;
8456 rsurface.batchnormal3f_bufferoffset = 0;
8457 rsurface.batchlightmapcolor4f = NULL;
8458 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8459 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8460 rsurface.batchtexcoordtexture2f = NULL;
8461 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8462 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8463 rsurface.batchtexcoordlightmap2f = NULL;
8464 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8465 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8466 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8467 rsurface.batchelement3i_indexbuffer = NULL;
8468 rsurface.batchelement3i_bufferoffset = 0;
8469 rsurface.batchelement3s = NULL;
8470 rsurface.batchelement3s_indexbuffer = NULL;
8471 rsurface.batchelement3s_bufferoffset = 0;
8472 // we'll only be setting up certain arrays as needed
8473 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8474 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8475 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8476 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8477 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8478 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8479 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8481 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8482 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8484 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8485 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8486 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8487 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8488 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8489 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8492 for (i = 0;i < texturenumsurfaces;i++)
8494 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8495 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8496 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8497 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8498 // copy only the data requested
8499 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8500 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8501 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8503 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8504 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8505 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8506 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8507 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8509 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8510 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8512 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8513 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8514 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8515 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8516 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8517 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8519 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8520 numvertices += surfacenumvertices;
8521 numtriangles += surfacenumtriangles;
8524 // generate a 16bit index array as well if possible
8525 // (in general, dynamic batches fit)
8526 if (numvertices <= 65536)
8528 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8529 for (i = 0;i < numtriangles*3;i++)
8530 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8533 // since we've copied everything, the batch now starts at 0
8534 rsurface.batchfirstvertex = 0;
8535 rsurface.batchnumvertices = batchnumvertices;
8536 rsurface.batchfirsttriangle = 0;
8537 rsurface.batchnumtriangles = batchnumtriangles;
8540 // q1bsp surfaces rendered in vertex color mode have to have colors
8541 // calculated based on lightstyles
8542 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8544 // generate color arrays for the surfaces in this list
8549 const unsigned char *lm;
8550 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8551 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8552 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8554 for (i = 0;i < texturenumsurfaces;i++)
8556 surface = texturesurfacelist[i];
8557 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8558 surfacenumvertices = surface->num_vertices;
8559 if (surface->lightmapinfo->samples)
8561 for (j = 0;j < surfacenumvertices;j++)
8563 lm = surface->lightmapinfo->samples + offsets[j];
8564 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8565 VectorScale(lm, scale, c);
8566 if (surface->lightmapinfo->styles[1] != 255)
8568 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8570 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8571 VectorMA(c, scale, lm, c);
8572 if (surface->lightmapinfo->styles[2] != 255)
8575 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8576 VectorMA(c, scale, lm, c);
8577 if (surface->lightmapinfo->styles[3] != 255)
8580 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8581 VectorMA(c, scale, lm, c);
8588 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);
8594 for (j = 0;j < surfacenumvertices;j++)
8596 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8603 // if vertices are deformed (sprite flares and things in maps, possibly
8604 // water waves, bulges and other deformations), modify the copied vertices
8606 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8608 switch (deform->deform)
8611 case Q3DEFORM_PROJECTIONSHADOW:
8612 case Q3DEFORM_TEXT0:
8613 case Q3DEFORM_TEXT1:
8614 case Q3DEFORM_TEXT2:
8615 case Q3DEFORM_TEXT3:
8616 case Q3DEFORM_TEXT4:
8617 case Q3DEFORM_TEXT5:
8618 case Q3DEFORM_TEXT6:
8619 case Q3DEFORM_TEXT7:
8622 case Q3DEFORM_AUTOSPRITE:
8623 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8624 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8625 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8626 VectorNormalize(newforward);
8627 VectorNormalize(newright);
8628 VectorNormalize(newup);
8629 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8630 // rsurface.batchvertex3f_vertexbuffer = NULL;
8631 // rsurface.batchvertex3f_bufferoffset = 0;
8632 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8633 // rsurface.batchsvector3f_vertexbuffer = NULL;
8634 // rsurface.batchsvector3f_bufferoffset = 0;
8635 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8636 // rsurface.batchtvector3f_vertexbuffer = NULL;
8637 // rsurface.batchtvector3f_bufferoffset = 0;
8638 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8639 // rsurface.batchnormal3f_vertexbuffer = NULL;
8640 // rsurface.batchnormal3f_bufferoffset = 0;
8641 // a single autosprite surface can contain multiple sprites...
8642 for (j = 0;j < batchnumvertices - 3;j += 4)
8644 VectorClear(center);
8645 for (i = 0;i < 4;i++)
8646 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8647 VectorScale(center, 0.25f, center);
8648 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8649 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8650 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8651 for (i = 0;i < 4;i++)
8653 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8654 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8657 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8658 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8659 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);
8661 case Q3DEFORM_AUTOSPRITE2:
8662 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8663 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8664 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8665 VectorNormalize(newforward);
8666 VectorNormalize(newright);
8667 VectorNormalize(newup);
8668 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8669 // rsurface.batchvertex3f_vertexbuffer = NULL;
8670 // rsurface.batchvertex3f_bufferoffset = 0;
8672 const float *v1, *v2;
8682 memset(shortest, 0, sizeof(shortest));
8683 // a single autosprite surface can contain multiple sprites...
8684 for (j = 0;j < batchnumvertices - 3;j += 4)
8686 VectorClear(center);
8687 for (i = 0;i < 4;i++)
8688 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8689 VectorScale(center, 0.25f, center);
8690 // find the two shortest edges, then use them to define the
8691 // axis vectors for rotating around the central axis
8692 for (i = 0;i < 6;i++)
8694 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8695 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8696 l = VectorDistance2(v1, v2);
8697 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8699 l += (1.0f / 1024.0f);
8700 if (shortest[0].length2 > l || i == 0)
8702 shortest[1] = shortest[0];
8703 shortest[0].length2 = l;
8704 shortest[0].v1 = v1;
8705 shortest[0].v2 = v2;
8707 else if (shortest[1].length2 > l || i == 1)
8709 shortest[1].length2 = l;
8710 shortest[1].v1 = v1;
8711 shortest[1].v2 = v2;
8714 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8715 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8716 // this calculates the right vector from the shortest edge
8717 // and the up vector from the edge midpoints
8718 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8719 VectorNormalize(right);
8720 VectorSubtract(end, start, up);
8721 VectorNormalize(up);
8722 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8723 VectorSubtract(rsurface.localvieworigin, center, forward);
8724 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8725 VectorNegate(forward, forward);
8726 VectorReflect(forward, 0, up, forward);
8727 VectorNormalize(forward);
8728 CrossProduct(up, forward, newright);
8729 VectorNormalize(newright);
8730 // rotate the quad around the up axis vector, this is made
8731 // especially easy by the fact we know the quad is flat,
8732 // so we only have to subtract the center position and
8733 // measure distance along the right vector, and then
8734 // multiply that by the newright vector and add back the
8736 // we also need to subtract the old position to undo the
8737 // displacement from the center, which we do with a
8738 // DotProduct, the subtraction/addition of center is also
8739 // optimized into DotProducts here
8740 l = DotProduct(right, center);
8741 for (i = 0;i < 4;i++)
8743 v1 = rsurface.batchvertex3f + 3*(j+i);
8744 f = DotProduct(right, v1) - l;
8745 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8749 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8751 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8752 // rsurface.batchnormal3f_vertexbuffer = NULL;
8753 // rsurface.batchnormal3f_bufferoffset = 0;
8754 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8756 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8758 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8759 // rsurface.batchsvector3f_vertexbuffer = NULL;
8760 // rsurface.batchsvector3f_bufferoffset = 0;
8761 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8762 // rsurface.batchtvector3f_vertexbuffer = NULL;
8763 // rsurface.batchtvector3f_bufferoffset = 0;
8764 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);
8767 case Q3DEFORM_NORMAL:
8768 // deform the normals to make reflections wavey
8769 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8770 rsurface.batchnormal3f_vertexbuffer = NULL;
8771 rsurface.batchnormal3f_bufferoffset = 0;
8772 for (j = 0;j < batchnumvertices;j++)
8775 float *normal = rsurface.batchnormal3f + 3*j;
8776 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8777 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8778 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]);
8779 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]);
8780 VectorNormalize(normal);
8782 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8784 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8785 // rsurface.batchsvector3f_vertexbuffer = NULL;
8786 // rsurface.batchsvector3f_bufferoffset = 0;
8787 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8788 // rsurface.batchtvector3f_vertexbuffer = NULL;
8789 // rsurface.batchtvector3f_bufferoffset = 0;
8790 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);
8794 // deform vertex array to make wavey water and flags and such
8795 waveparms[0] = deform->waveparms[0];
8796 waveparms[1] = deform->waveparms[1];
8797 waveparms[2] = deform->waveparms[2];
8798 waveparms[3] = deform->waveparms[3];
8799 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8800 break; // if wavefunc is a nop, don't make a dynamic vertex array
8801 // this is how a divisor of vertex influence on deformation
8802 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8803 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8804 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8805 // rsurface.batchvertex3f_vertexbuffer = NULL;
8806 // rsurface.batchvertex3f_bufferoffset = 0;
8807 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8808 // rsurface.batchnormal3f_vertexbuffer = NULL;
8809 // rsurface.batchnormal3f_bufferoffset = 0;
8810 for (j = 0;j < batchnumvertices;j++)
8812 // if the wavefunc depends on time, evaluate it per-vertex
8815 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8816 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8818 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8820 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8821 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8822 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8824 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8825 // rsurface.batchsvector3f_vertexbuffer = NULL;
8826 // rsurface.batchsvector3f_bufferoffset = 0;
8827 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8828 // rsurface.batchtvector3f_vertexbuffer = NULL;
8829 // rsurface.batchtvector3f_bufferoffset = 0;
8830 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);
8833 case Q3DEFORM_BULGE:
8834 // deform vertex array to make the surface have moving bulges
8835 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8836 // rsurface.batchvertex3f_vertexbuffer = NULL;
8837 // rsurface.batchvertex3f_bufferoffset = 0;
8838 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8839 // rsurface.batchnormal3f_vertexbuffer = NULL;
8840 // rsurface.batchnormal3f_bufferoffset = 0;
8841 for (j = 0;j < batchnumvertices;j++)
8843 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8844 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8846 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8847 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8848 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8850 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8851 // rsurface.batchsvector3f_vertexbuffer = NULL;
8852 // rsurface.batchsvector3f_bufferoffset = 0;
8853 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8854 // rsurface.batchtvector3f_vertexbuffer = NULL;
8855 // rsurface.batchtvector3f_bufferoffset = 0;
8856 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);
8860 // deform vertex array
8861 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8862 break; // if wavefunc is a nop, don't make a dynamic vertex array
8863 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8864 VectorScale(deform->parms, scale, waveparms);
8865 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8866 // rsurface.batchvertex3f_vertexbuffer = NULL;
8867 // rsurface.batchvertex3f_bufferoffset = 0;
8868 for (j = 0;j < batchnumvertices;j++)
8869 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8874 // generate texcoords based on the chosen texcoord source
8875 switch(rsurface.texture->tcgen.tcgen)
8878 case Q3TCGEN_TEXTURE:
8880 case Q3TCGEN_LIGHTMAP:
8881 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8882 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8883 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8884 if (rsurface.batchtexcoordlightmap2f)
8885 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8887 case Q3TCGEN_VECTOR:
8888 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8889 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8890 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8891 for (j = 0;j < batchnumvertices;j++)
8893 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8894 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8897 case Q3TCGEN_ENVIRONMENT:
8898 // make environment reflections using a spheremap
8899 rsurface.batchtexcoordtexture2f = (float *)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 // identical to Q3A's method, but executed in worldspace so
8905 // carried models can be shiny too
8907 float viewer[3], d, reflected[3], worldreflected[3];
8909 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8910 // VectorNormalize(viewer);
8912 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8914 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8915 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8916 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8917 // note: this is proportinal to viewer, so we can normalize later
8919 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8920 VectorNormalize(worldreflected);
8922 // note: this sphere map only uses world x and z!
8923 // so positive and negative y will LOOK THE SAME.
8924 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8925 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8929 // the only tcmod that needs software vertex processing is turbulent, so
8930 // check for it here and apply the changes if needed
8931 // and we only support that as the first one
8932 // (handling a mixture of turbulent and other tcmods would be problematic
8933 // without punting it entirely to a software path)
8934 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8936 amplitude = rsurface.texture->tcmods[0].parms[1];
8937 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8938 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8939 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8940 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8941 for (j = 0;j < batchnumvertices;j++)
8943 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);
8944 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8948 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8950 // convert the modified arrays to vertex structs
8951 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8952 // rsurface.batchvertexmeshbuffer = NULL;
8953 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8954 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8955 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8956 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8957 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8958 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
8959 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
8961 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8963 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
8964 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
8967 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
8968 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8969 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
8970 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
8971 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8972 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
8973 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
8974 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8975 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
8979 void RSurf_DrawBatch(void)
8981 // sometimes a zero triangle surface (usually a degenerate patch) makes it
8982 // through the pipeline, killing it earlier in the pipeline would have
8983 // per-surface overhead rather than per-batch overhead, so it's best to
8984 // reject it here, before it hits glDraw.
8985 if (rsurface.batchnumtriangles == 0)
8988 // batch debugging code
8989 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
8995 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
8996 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
8999 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9001 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9003 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9004 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);
9011 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);
9014 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9016 // pick the closest matching water plane
9017 int planeindex, vertexindex, bestplaneindex = -1;
9021 r_waterstate_waterplane_t *p;
9022 qboolean prepared = false;
9024 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9026 if(p->camera_entity != rsurface.texture->camera_entity)
9031 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9033 if(rsurface.batchnumvertices == 0)
9036 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9038 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9039 d += fabs(PlaneDiff(vert, &p->plane));
9041 if (bestd > d || bestplaneindex < 0)
9044 bestplaneindex = planeindex;
9047 return bestplaneindex;
9048 // NOTE: this MAY return a totally unrelated water plane; we can ignore
9049 // this situation though, as it might be better to render single larger
9050 // batches with useless stuff (backface culled for example) than to
9051 // render multiple smaller batches
9054 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9057 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9058 rsurface.passcolor4f_vertexbuffer = 0;
9059 rsurface.passcolor4f_bufferoffset = 0;
9060 for (i = 0;i < rsurface.batchnumvertices;i++)
9061 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9064 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9071 if (rsurface.passcolor4f)
9073 // generate color arrays
9074 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9075 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9076 rsurface.passcolor4f_vertexbuffer = 0;
9077 rsurface.passcolor4f_bufferoffset = 0;
9078 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)
9080 f = RSurf_FogVertex(v);
9089 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9090 rsurface.passcolor4f_vertexbuffer = 0;
9091 rsurface.passcolor4f_bufferoffset = 0;
9092 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9094 f = RSurf_FogVertex(v);
9103 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9110 if (!rsurface.passcolor4f)
9112 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9113 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9114 rsurface.passcolor4f_vertexbuffer = 0;
9115 rsurface.passcolor4f_bufferoffset = 0;
9116 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)
9118 f = RSurf_FogVertex(v);
9119 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9120 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9121 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9126 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9131 if (!rsurface.passcolor4f)
9133 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9134 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9135 rsurface.passcolor4f_vertexbuffer = 0;
9136 rsurface.passcolor4f_bufferoffset = 0;
9137 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9146 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9151 if (!rsurface.passcolor4f)
9153 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9154 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9155 rsurface.passcolor4f_vertexbuffer = 0;
9156 rsurface.passcolor4f_bufferoffset = 0;
9157 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9159 c2[0] = c[0] + r_refdef.scene.ambient;
9160 c2[1] = c[1] + r_refdef.scene.ambient;
9161 c2[2] = c[2] + r_refdef.scene.ambient;
9166 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9169 rsurface.passcolor4f = NULL;
9170 rsurface.passcolor4f_vertexbuffer = 0;
9171 rsurface.passcolor4f_bufferoffset = 0;
9172 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9173 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9174 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9175 GL_Color(r, g, b, a);
9176 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9180 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9182 // TODO: optimize applyfog && applycolor case
9183 // just apply fog if necessary, and tint the fog color array if necessary
9184 rsurface.passcolor4f = NULL;
9185 rsurface.passcolor4f_vertexbuffer = 0;
9186 rsurface.passcolor4f_bufferoffset = 0;
9187 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9188 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9189 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9190 GL_Color(r, g, b, a);
9194 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9197 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9198 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9199 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9200 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9201 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9202 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9203 GL_Color(r, g, b, a);
9207 static void RSurf_DrawBatch_GL11_ClampColor(void)
9212 if (!rsurface.passcolor4f)
9214 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9216 c2[0] = bound(0.0f, c1[0], 1.0f);
9217 c2[1] = bound(0.0f, c1[1], 1.0f);
9218 c2[2] = bound(0.0f, c1[2], 1.0f);
9219 c2[3] = bound(0.0f, c1[3], 1.0f);
9223 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9233 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9234 rsurface.passcolor4f_vertexbuffer = 0;
9235 rsurface.passcolor4f_bufferoffset = 0;
9236 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)
9238 f = -DotProduct(r_refdef.view.forward, n);
9240 f = f * 0.85 + 0.15; // work around so stuff won't get black
9241 f *= r_refdef.lightmapintensity;
9242 Vector4Set(c, f, f, f, 1);
9246 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9248 RSurf_DrawBatch_GL11_ApplyFakeLight();
9249 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9250 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9251 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9252 GL_Color(r, g, b, a);
9256 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9264 vec3_t ambientcolor;
9265 vec3_t diffusecolor;
9269 VectorCopy(rsurface.modellight_lightdir, lightdir);
9270 f = 0.5f * r_refdef.lightmapintensity;
9271 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9272 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9273 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9274 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9275 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9276 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9278 if (VectorLength2(diffusecolor) > 0)
9280 // q3-style directional shading
9281 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9282 rsurface.passcolor4f_vertexbuffer = 0;
9283 rsurface.passcolor4f_bufferoffset = 0;
9284 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)
9286 if ((f = DotProduct(n, lightdir)) > 0)
9287 VectorMA(ambientcolor, f, diffusecolor, c);
9289 VectorCopy(ambientcolor, c);
9296 *applycolor = false;
9300 *r = ambientcolor[0];
9301 *g = ambientcolor[1];
9302 *b = ambientcolor[2];
9303 rsurface.passcolor4f = NULL;
9304 rsurface.passcolor4f_vertexbuffer = 0;
9305 rsurface.passcolor4f_bufferoffset = 0;
9309 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9311 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9312 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9313 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9314 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9315 GL_Color(r, g, b, a);
9319 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9327 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9328 rsurface.passcolor4f_vertexbuffer = 0;
9329 rsurface.passcolor4f_bufferoffset = 0;
9331 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9333 f = 1 - RSurf_FogVertex(v);
9341 void RSurf_SetupDepthAndCulling(void)
9343 // submodels are biased to avoid z-fighting with world surfaces that they
9344 // may be exactly overlapping (avoids z-fighting artifacts on certain
9345 // doors and things in Quake maps)
9346 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9347 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9348 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9349 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9352 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9354 // transparent sky would be ridiculous
9355 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9357 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9358 skyrenderlater = true;
9359 RSurf_SetupDepthAndCulling();
9361 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9362 // skymasking on them, and Quake3 never did sky masking (unlike
9363 // software Quake and software Quake2), so disable the sky masking
9364 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9365 // and skymasking also looks very bad when noclipping outside the
9366 // level, so don't use it then either.
9367 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9369 R_Mesh_ResetTextureState();
9370 if (skyrendermasked)
9372 R_SetupShader_DepthOrShadow();
9373 // depth-only (masking)
9374 GL_ColorMask(0,0,0,0);
9375 // just to make sure that braindead drivers don't draw
9376 // anything despite that colormask...
9377 GL_BlendFunc(GL_ZERO, GL_ONE);
9378 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9379 if (rsurface.batchvertex3fbuffer)
9380 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9382 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9386 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9388 GL_BlendFunc(GL_ONE, GL_ZERO);
9389 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9390 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9391 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9394 if (skyrendermasked)
9395 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9397 R_Mesh_ResetTextureState();
9398 GL_Color(1, 1, 1, 1);
9401 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9402 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9403 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9405 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9409 // render screenspace normalmap to texture
9411 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9416 // bind lightmap texture
9418 // water/refraction/reflection/camera surfaces have to be handled specially
9419 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9421 int start, end, startplaneindex;
9422 for (start = 0;start < texturenumsurfaces;start = end)
9424 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9425 if(startplaneindex < 0)
9427 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9428 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9432 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9434 // now that we have a batch using the same planeindex, render it
9435 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9437 // render water or distortion background
9439 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));
9441 // blend surface on top
9442 GL_DepthMask(false);
9443 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9446 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9448 // render surface with reflection texture as input
9449 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9450 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));
9457 // render surface batch normally
9458 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9459 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9463 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9465 // OpenGL 1.3 path - anything not completely ancient
9466 qboolean applycolor;
9469 const texturelayer_t *layer;
9470 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);
9471 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9473 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9476 int layertexrgbscale;
9477 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9479 if (layerindex == 0)
9483 GL_AlphaTest(false);
9484 GL_DepthFunc(GL_EQUAL);
9487 GL_DepthMask(layer->depthmask && writedepth);
9488 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9489 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9491 layertexrgbscale = 4;
9492 VectorScale(layer->color, 0.25f, layercolor);
9494 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9496 layertexrgbscale = 2;
9497 VectorScale(layer->color, 0.5f, layercolor);
9501 layertexrgbscale = 1;
9502 VectorScale(layer->color, 1.0f, layercolor);
9504 layercolor[3] = layer->color[3];
9505 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9506 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9507 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9508 switch (layer->type)
9510 case TEXTURELAYERTYPE_LITTEXTURE:
9511 // single-pass lightmapped texture with 2x rgbscale
9512 R_Mesh_TexBind(0, r_texture_white);
9513 R_Mesh_TexMatrix(0, NULL);
9514 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9515 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9516 R_Mesh_TexBind(1, layer->texture);
9517 R_Mesh_TexMatrix(1, &layer->texmatrix);
9518 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9519 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9520 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9521 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9522 else if (FAKELIGHT_ENABLED)
9523 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9524 else if (rsurface.uselightmaptexture)
9525 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9527 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9529 case TEXTURELAYERTYPE_TEXTURE:
9530 // singletexture unlit texture with transparency support
9531 R_Mesh_TexBind(0, layer->texture);
9532 R_Mesh_TexMatrix(0, &layer->texmatrix);
9533 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9534 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9535 R_Mesh_TexBind(1, 0);
9536 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9537 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9539 case TEXTURELAYERTYPE_FOG:
9540 // singletexture fogging
9543 R_Mesh_TexBind(0, layer->texture);
9544 R_Mesh_TexMatrix(0, &layer->texmatrix);
9545 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9546 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9550 R_Mesh_TexBind(0, 0);
9551 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9553 R_Mesh_TexBind(1, 0);
9554 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9555 // generate a color array for the fog pass
9556 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9557 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9561 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9564 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9566 GL_DepthFunc(GL_LEQUAL);
9567 GL_AlphaTest(false);
9571 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9573 // OpenGL 1.1 - crusty old voodoo path
9576 const texturelayer_t *layer;
9577 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);
9578 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9580 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9582 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9584 if (layerindex == 0)
9588 GL_AlphaTest(false);
9589 GL_DepthFunc(GL_EQUAL);
9592 GL_DepthMask(layer->depthmask && writedepth);
9593 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9594 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9595 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9596 switch (layer->type)
9598 case TEXTURELAYERTYPE_LITTEXTURE:
9599 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9601 // two-pass lit texture with 2x rgbscale
9602 // first the lightmap pass
9603 R_Mesh_TexBind(0, r_texture_white);
9604 R_Mesh_TexMatrix(0, NULL);
9605 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9606 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9607 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9608 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9609 else if (FAKELIGHT_ENABLED)
9610 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9611 else if (rsurface.uselightmaptexture)
9612 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9614 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9615 // then apply the texture to it
9616 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9617 R_Mesh_TexBind(0, layer->texture);
9618 R_Mesh_TexMatrix(0, &layer->texmatrix);
9619 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9620 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9621 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);
9625 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9626 R_Mesh_TexBind(0, layer->texture);
9627 R_Mesh_TexMatrix(0, &layer->texmatrix);
9628 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9629 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9630 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9631 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);
9633 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);
9636 case TEXTURELAYERTYPE_TEXTURE:
9637 // singletexture unlit texture with transparency support
9638 R_Mesh_TexBind(0, layer->texture);
9639 R_Mesh_TexMatrix(0, &layer->texmatrix);
9640 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9641 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9642 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);
9644 case TEXTURELAYERTYPE_FOG:
9645 // singletexture fogging
9648 R_Mesh_TexBind(0, layer->texture);
9649 R_Mesh_TexMatrix(0, &layer->texmatrix);
9650 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9651 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9655 R_Mesh_TexBind(0, 0);
9656 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9658 // generate a color array for the fog pass
9659 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9660 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9664 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9667 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9669 GL_DepthFunc(GL_LEQUAL);
9670 GL_AlphaTest(false);
9674 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9678 r_vertexgeneric_t *batchvertex;
9681 // R_Mesh_ResetTextureState();
9682 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9684 if(rsurface.texture && rsurface.texture->currentskinframe)
9686 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9687 c[3] *= rsurface.texture->currentalpha;
9697 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9699 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9700 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9701 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9704 // brighten it up (as texture value 127 means "unlit")
9705 c[0] *= 2 * r_refdef.view.colorscale;
9706 c[1] *= 2 * r_refdef.view.colorscale;
9707 c[2] *= 2 * r_refdef.view.colorscale;
9709 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9710 c[3] *= r_wateralpha.value;
9712 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9714 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9715 GL_DepthMask(false);
9717 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9719 GL_BlendFunc(GL_ONE, GL_ONE);
9720 GL_DepthMask(false);
9722 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9724 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9725 GL_DepthMask(false);
9727 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9729 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9730 GL_DepthMask(false);
9734 GL_BlendFunc(GL_ONE, GL_ZERO);
9735 GL_DepthMask(writedepth);
9738 if (r_showsurfaces.integer == 3)
9740 rsurface.passcolor4f = NULL;
9742 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9744 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9746 rsurface.passcolor4f = NULL;
9747 rsurface.passcolor4f_vertexbuffer = 0;
9748 rsurface.passcolor4f_bufferoffset = 0;
9750 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9752 qboolean applycolor = true;
9755 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9757 r_refdef.lightmapintensity = 1;
9758 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9759 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9761 else if (FAKELIGHT_ENABLED)
9763 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9765 r_refdef.lightmapintensity = r_fakelight_intensity.value;
9766 RSurf_DrawBatch_GL11_ApplyFakeLight();
9767 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9771 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9773 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9774 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9775 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9778 if(!rsurface.passcolor4f)
9779 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9781 RSurf_DrawBatch_GL11_ApplyAmbient();
9782 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9783 if(r_refdef.fogenabled)
9784 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9785 RSurf_DrawBatch_GL11_ClampColor();
9787 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9788 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9791 else if (!r_refdef.view.showdebug)
9793 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9794 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9795 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9797 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9798 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9800 R_Mesh_PrepareVertices_Generic_Unlock();
9803 else if (r_showsurfaces.integer == 4)
9805 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9806 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9807 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9809 unsigned char c = (vi << 3) * (1.0f / 256.0f);
9810 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9811 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9813 R_Mesh_PrepareVertices_Generic_Unlock();
9816 else if (r_showsurfaces.integer == 2)
9819 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9820 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9821 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9823 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9824 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9825 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9826 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9827 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9828 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9829 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9831 R_Mesh_PrepareVertices_Generic_Unlock();
9832 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9836 int texturesurfaceindex;
9838 const msurface_t *surface;
9839 float surfacecolor4f[4];
9840 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9841 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9843 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9845 surface = texturesurfacelist[texturesurfaceindex];
9846 k = (int)(((size_t)surface) / sizeof(msurface_t));
9847 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9848 for (j = 0;j < surface->num_vertices;j++)
9850 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9851 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9855 R_Mesh_PrepareVertices_Generic_Unlock();
9860 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9863 RSurf_SetupDepthAndCulling();
9864 if (r_showsurfaces.integer)
9866 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9869 switch (vid.renderpath)
9871 case RENDERPATH_GL20:
9872 case RENDERPATH_D3D9:
9873 case RENDERPATH_D3D10:
9874 case RENDERPATH_D3D11:
9875 case RENDERPATH_SOFT:
9876 case RENDERPATH_GLES2:
9877 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9879 case RENDERPATH_GL13:
9880 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9882 case RENDERPATH_GL11:
9883 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9889 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9892 RSurf_SetupDepthAndCulling();
9893 if (r_showsurfaces.integer)
9895 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9898 switch (vid.renderpath)
9900 case RENDERPATH_GL20:
9901 case RENDERPATH_D3D9:
9902 case RENDERPATH_D3D10:
9903 case RENDERPATH_D3D11:
9904 case RENDERPATH_SOFT:
9905 case RENDERPATH_GLES2:
9906 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9908 case RENDERPATH_GL13:
9909 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9911 case RENDERPATH_GL11:
9912 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9918 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9921 int texturenumsurfaces, endsurface;
9923 const msurface_t *surface;
9924 #define MAXBATCH_TRANSPARENTSURFACES 256
9925 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9927 // if the model is static it doesn't matter what value we give for
9928 // wantnormals and wanttangents, so this logic uses only rules applicable
9929 // to a model, knowing that they are meaningless otherwise
9930 if (ent == r_refdef.scene.worldentity)
9931 RSurf_ActiveWorldEntity();
9932 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9933 RSurf_ActiveModelEntity(ent, false, false, false);
9936 switch (vid.renderpath)
9938 case RENDERPATH_GL20:
9939 case RENDERPATH_D3D9:
9940 case RENDERPATH_D3D10:
9941 case RENDERPATH_D3D11:
9942 case RENDERPATH_SOFT:
9943 case RENDERPATH_GLES2:
9944 RSurf_ActiveModelEntity(ent, true, true, false);
9946 case RENDERPATH_GL13:
9947 case RENDERPATH_GL11:
9948 RSurf_ActiveModelEntity(ent, true, false, false);
9953 if (r_transparentdepthmasking.integer)
9955 qboolean setup = false;
9956 for (i = 0;i < numsurfaces;i = j)
9959 surface = rsurface.modelsurfaces + surfacelist[i];
9960 texture = surface->texture;
9961 rsurface.texture = R_GetCurrentTexture(texture);
9962 rsurface.lightmaptexture = NULL;
9963 rsurface.deluxemaptexture = NULL;
9964 rsurface.uselightmaptexture = false;
9965 // scan ahead until we find a different texture
9966 endsurface = min(i + 1024, numsurfaces);
9967 texturenumsurfaces = 0;
9968 texturesurfacelist[texturenumsurfaces++] = surface;
9969 for (;j < endsurface;j++)
9971 surface = rsurface.modelsurfaces + surfacelist[j];
9972 if (texture != surface->texture)
9974 texturesurfacelist[texturenumsurfaces++] = surface;
9976 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9978 // render the range of surfaces as depth
9982 GL_ColorMask(0,0,0,0);
9985 GL_BlendFunc(GL_ONE, GL_ZERO);
9987 // R_Mesh_ResetTextureState();
9988 R_SetupShader_DepthOrShadow();
9990 RSurf_SetupDepthAndCulling();
9991 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9992 if (rsurface.batchvertex3fbuffer)
9993 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9995 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9999 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10002 for (i = 0;i < numsurfaces;i = j)
10005 surface = rsurface.modelsurfaces + surfacelist[i];
10006 texture = surface->texture;
10007 rsurface.texture = R_GetCurrentTexture(texture);
10008 // scan ahead until we find a different texture
10009 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
10010 texturenumsurfaces = 0;
10011 texturesurfacelist[texturenumsurfaces++] = surface;
10012 if(FAKELIGHT_ENABLED)
10014 rsurface.lightmaptexture = NULL;
10015 rsurface.deluxemaptexture = NULL;
10016 rsurface.uselightmaptexture = false;
10017 for (;j < endsurface;j++)
10019 surface = rsurface.modelsurfaces + surfacelist[j];
10020 if (texture != surface->texture)
10022 texturesurfacelist[texturenumsurfaces++] = surface;
10027 rsurface.lightmaptexture = surface->lightmaptexture;
10028 rsurface.deluxemaptexture = surface->deluxemaptexture;
10029 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10030 for (;j < endsurface;j++)
10032 surface = rsurface.modelsurfaces + surfacelist[j];
10033 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10035 texturesurfacelist[texturenumsurfaces++] = surface;
10038 // render the range of surfaces
10039 if (ent == r_refdef.scene.worldentity)
10040 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10042 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10044 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10047 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10049 // transparent surfaces get pushed off into the transparent queue
10050 int surfacelistindex;
10051 const msurface_t *surface;
10052 vec3_t tempcenter, center;
10053 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10055 surface = texturesurfacelist[surfacelistindex];
10056 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10057 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10058 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10059 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10060 if (queueentity->transparent_offset) // transparent offset
10062 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10063 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10064 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10066 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10070 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10072 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10074 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10076 RSurf_SetupDepthAndCulling();
10077 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10078 if (rsurface.batchvertex3fbuffer)
10079 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10081 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10085 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10087 const entity_render_t *queueentity = r_refdef.scene.worldentity;
10090 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10093 if (!rsurface.texture->currentnumlayers)
10095 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10096 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10098 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10100 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10101 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10102 else if (!rsurface.texture->currentnumlayers)
10104 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10106 // in the deferred case, transparent surfaces were queued during prepass
10107 if (!r_shadow_usingdeferredprepass)
10108 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10112 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10113 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10118 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10121 texture_t *texture;
10122 R_FrameData_SetMark();
10123 // break the surface list down into batches by texture and use of lightmapping
10124 for (i = 0;i < numsurfaces;i = j)
10127 // texture is the base texture pointer, rsurface.texture is the
10128 // current frame/skin the texture is directing us to use (for example
10129 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10130 // use skin 1 instead)
10131 texture = surfacelist[i]->texture;
10132 rsurface.texture = R_GetCurrentTexture(texture);
10133 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10135 // if this texture is not the kind we want, skip ahead to the next one
10136 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10140 if(FAKELIGHT_ENABLED || depthonly || prepass)
10142 rsurface.lightmaptexture = NULL;
10143 rsurface.deluxemaptexture = NULL;
10144 rsurface.uselightmaptexture = false;
10145 // simply scan ahead until we find a different texture or lightmap state
10146 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10151 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10152 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10153 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10154 // simply scan ahead until we find a different texture or lightmap state
10155 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10158 // render the range of surfaces
10159 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10161 R_FrameData_ReturnToMark();
10164 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10168 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10171 if (!rsurface.texture->currentnumlayers)
10173 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10174 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10176 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10178 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10179 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10180 else if (!rsurface.texture->currentnumlayers)
10182 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10184 // in the deferred case, transparent surfaces were queued during prepass
10185 if (!r_shadow_usingdeferredprepass)
10186 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10190 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10191 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10196 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10199 texture_t *texture;
10200 R_FrameData_SetMark();
10201 // break the surface list down into batches by texture and use of lightmapping
10202 for (i = 0;i < numsurfaces;i = j)
10205 // texture is the base texture pointer, rsurface.texture is the
10206 // current frame/skin the texture is directing us to use (for example
10207 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10208 // use skin 1 instead)
10209 texture = surfacelist[i]->texture;
10210 rsurface.texture = R_GetCurrentTexture(texture);
10211 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10213 // if this texture is not the kind we want, skip ahead to the next one
10214 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10218 if(FAKELIGHT_ENABLED || depthonly || prepass)
10220 rsurface.lightmaptexture = NULL;
10221 rsurface.deluxemaptexture = NULL;
10222 rsurface.uselightmaptexture = false;
10223 // simply scan ahead until we find a different texture or lightmap state
10224 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10229 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10230 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10231 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10232 // simply scan ahead until we find a different texture or lightmap state
10233 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10236 // render the range of surfaces
10237 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10239 R_FrameData_ReturnToMark();
10242 float locboxvertex3f[6*4*3] =
10244 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10245 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10246 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10247 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10248 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10249 1,0,0, 0,0,0, 0,1,0, 1,1,0
10252 unsigned short locboxelements[6*2*3] =
10257 12,13,14, 12,14,15,
10258 16,17,18, 16,18,19,
10262 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10265 cl_locnode_t *loc = (cl_locnode_t *)ent;
10267 float vertex3f[6*4*3];
10269 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10270 GL_DepthMask(false);
10271 GL_DepthRange(0, 1);
10272 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10273 GL_DepthTest(true);
10274 GL_CullFace(GL_NONE);
10275 R_EntityMatrix(&identitymatrix);
10277 // R_Mesh_ResetTextureState();
10279 i = surfacelist[0];
10280 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10281 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10282 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10283 surfacelist[0] < 0 ? 0.5f : 0.125f);
10285 if (VectorCompare(loc->mins, loc->maxs))
10287 VectorSet(size, 2, 2, 2);
10288 VectorMA(loc->mins, -0.5f, size, mins);
10292 VectorCopy(loc->mins, mins);
10293 VectorSubtract(loc->maxs, loc->mins, size);
10296 for (i = 0;i < 6*4*3;)
10297 for (j = 0;j < 3;j++, i++)
10298 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10300 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10301 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10302 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10305 void R_DrawLocs(void)
10308 cl_locnode_t *loc, *nearestloc;
10310 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10311 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10313 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10314 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10318 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10320 if (decalsystem->decals)
10321 Mem_Free(decalsystem->decals);
10322 memset(decalsystem, 0, sizeof(*decalsystem));
10325 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)
10328 tridecal_t *decals;
10331 // expand or initialize the system
10332 if (decalsystem->maxdecals <= decalsystem->numdecals)
10334 decalsystem_t old = *decalsystem;
10335 qboolean useshortelements;
10336 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10337 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10338 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)));
10339 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10340 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10341 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10342 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10343 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10344 if (decalsystem->numdecals)
10345 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10347 Mem_Free(old.decals);
10348 for (i = 0;i < decalsystem->maxdecals*3;i++)
10349 decalsystem->element3i[i] = i;
10350 if (useshortelements)
10351 for (i = 0;i < decalsystem->maxdecals*3;i++)
10352 decalsystem->element3s[i] = i;
10355 // grab a decal and search for another free slot for the next one
10356 decals = decalsystem->decals;
10357 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10358 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10360 decalsystem->freedecal = i;
10361 if (decalsystem->numdecals <= i)
10362 decalsystem->numdecals = i + 1;
10364 // initialize the decal
10366 decal->triangleindex = triangleindex;
10367 decal->surfaceindex = surfaceindex;
10368 decal->decalsequence = decalsequence;
10369 decal->color4f[0][0] = c0[0];
10370 decal->color4f[0][1] = c0[1];
10371 decal->color4f[0][2] = c0[2];
10372 decal->color4f[0][3] = 1;
10373 decal->color4f[1][0] = c1[0];
10374 decal->color4f[1][1] = c1[1];
10375 decal->color4f[1][2] = c1[2];
10376 decal->color4f[1][3] = 1;
10377 decal->color4f[2][0] = c2[0];
10378 decal->color4f[2][1] = c2[1];
10379 decal->color4f[2][2] = c2[2];
10380 decal->color4f[2][3] = 1;
10381 decal->vertex3f[0][0] = v0[0];
10382 decal->vertex3f[0][1] = v0[1];
10383 decal->vertex3f[0][2] = v0[2];
10384 decal->vertex3f[1][0] = v1[0];
10385 decal->vertex3f[1][1] = v1[1];
10386 decal->vertex3f[1][2] = v1[2];
10387 decal->vertex3f[2][0] = v2[0];
10388 decal->vertex3f[2][1] = v2[1];
10389 decal->vertex3f[2][2] = v2[2];
10390 decal->texcoord2f[0][0] = t0[0];
10391 decal->texcoord2f[0][1] = t0[1];
10392 decal->texcoord2f[1][0] = t1[0];
10393 decal->texcoord2f[1][1] = t1[1];
10394 decal->texcoord2f[2][0] = t2[0];
10395 decal->texcoord2f[2][1] = t2[1];
10398 extern cvar_t cl_decals_bias;
10399 extern cvar_t cl_decals_models;
10400 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10401 // baseparms, parms, temps
10402 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)
10407 const float *vertex3f;
10408 const float *normal3f;
10410 float points[2][9][3];
10417 e = rsurface.modelelement3i + 3*triangleindex;
10419 vertex3f = rsurface.modelvertex3f;
10420 normal3f = rsurface.modelnormal3f;
10424 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10426 index = 3*e[cornerindex];
10427 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10432 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10434 index = 3*e[cornerindex];
10435 VectorCopy(vertex3f + index, v[cornerindex]);
10440 //TriangleNormal(v[0], v[1], v[2], normal);
10441 //if (DotProduct(normal, localnormal) < 0.0f)
10443 // clip by each of the box planes formed from the projection matrix
10444 // if anything survives, we emit the decal
10445 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]);
10448 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]);
10451 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]);
10454 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]);
10457 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]);
10460 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]);
10463 // some part of the triangle survived, so we have to accept it...
10466 // dynamic always uses the original triangle
10468 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10470 index = 3*e[cornerindex];
10471 VectorCopy(vertex3f + index, v[cornerindex]);
10474 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10476 // convert vertex positions to texcoords
10477 Matrix4x4_Transform(projection, v[cornerindex], temp);
10478 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10479 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10480 // calculate distance fade from the projection origin
10481 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10482 f = bound(0.0f, f, 1.0f);
10483 c[cornerindex][0] = r * f;
10484 c[cornerindex][1] = g * f;
10485 c[cornerindex][2] = b * f;
10486 c[cornerindex][3] = 1.0f;
10487 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10490 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);
10492 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10493 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);
10495 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)
10497 matrix4x4_t projection;
10498 decalsystem_t *decalsystem;
10501 const msurface_t *surface;
10502 const msurface_t *surfaces;
10503 const int *surfacelist;
10504 const texture_t *texture;
10506 int numsurfacelist;
10507 int surfacelistindex;
10510 float localorigin[3];
10511 float localnormal[3];
10512 float localmins[3];
10513 float localmaxs[3];
10516 float planes[6][4];
10519 int bih_triangles_count;
10520 int bih_triangles[256];
10521 int bih_surfaces[256];
10523 decalsystem = &ent->decalsystem;
10524 model = ent->model;
10525 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10527 R_DecalSystem_Reset(&ent->decalsystem);
10531 if (!model->brush.data_leafs && !cl_decals_models.integer)
10533 if (decalsystem->model)
10534 R_DecalSystem_Reset(decalsystem);
10538 if (decalsystem->model != model)
10539 R_DecalSystem_Reset(decalsystem);
10540 decalsystem->model = model;
10542 RSurf_ActiveModelEntity(ent, true, false, false);
10544 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10545 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10546 VectorNormalize(localnormal);
10547 localsize = worldsize*rsurface.inversematrixscale;
10548 localmins[0] = localorigin[0] - localsize;
10549 localmins[1] = localorigin[1] - localsize;
10550 localmins[2] = localorigin[2] - localsize;
10551 localmaxs[0] = localorigin[0] + localsize;
10552 localmaxs[1] = localorigin[1] + localsize;
10553 localmaxs[2] = localorigin[2] + localsize;
10555 //VectorCopy(localnormal, planes[4]);
10556 //VectorVectors(planes[4], planes[2], planes[0]);
10557 AnglesFromVectors(angles, localnormal, NULL, false);
10558 AngleVectors(angles, planes[0], planes[2], planes[4]);
10559 VectorNegate(planes[0], planes[1]);
10560 VectorNegate(planes[2], planes[3]);
10561 VectorNegate(planes[4], planes[5]);
10562 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10563 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10564 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10565 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10566 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10567 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10572 matrix4x4_t forwardprojection;
10573 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10574 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10579 float projectionvector[4][3];
10580 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10581 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10582 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10583 projectionvector[0][0] = planes[0][0] * ilocalsize;
10584 projectionvector[0][1] = planes[1][0] * ilocalsize;
10585 projectionvector[0][2] = planes[2][0] * ilocalsize;
10586 projectionvector[1][0] = planes[0][1] * ilocalsize;
10587 projectionvector[1][1] = planes[1][1] * ilocalsize;
10588 projectionvector[1][2] = planes[2][1] * ilocalsize;
10589 projectionvector[2][0] = planes[0][2] * ilocalsize;
10590 projectionvector[2][1] = planes[1][2] * ilocalsize;
10591 projectionvector[2][2] = planes[2][2] * ilocalsize;
10592 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10593 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10594 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10595 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10599 dynamic = model->surfmesh.isanimated;
10600 numsurfacelist = model->nummodelsurfaces;
10601 surfacelist = model->sortedmodelsurfaces;
10602 surfaces = model->data_surfaces;
10605 bih_triangles_count = -1;
10608 if(model->render_bih.numleafs)
10609 bih = &model->render_bih;
10610 else if(model->collision_bih.numleafs)
10611 bih = &model->collision_bih;
10614 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10615 if(bih_triangles_count == 0)
10617 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10619 if(bih_triangles_count > 0)
10621 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10623 surfaceindex = bih_surfaces[triangleindex];
10624 surface = surfaces + surfaceindex;
10625 texture = surface->texture;
10626 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10628 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10630 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10635 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10637 surfaceindex = surfacelist[surfacelistindex];
10638 surface = surfaces + surfaceindex;
10639 // check cull box first because it rejects more than any other check
10640 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10642 // skip transparent surfaces
10643 texture = surface->texture;
10644 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10646 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10648 numtriangles = surface->num_triangles;
10649 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10650 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10655 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10656 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)
10658 int renderentityindex;
10659 float worldmins[3];
10660 float worldmaxs[3];
10661 entity_render_t *ent;
10663 if (!cl_decals_newsystem.integer)
10666 worldmins[0] = worldorigin[0] - worldsize;
10667 worldmins[1] = worldorigin[1] - worldsize;
10668 worldmins[2] = worldorigin[2] - worldsize;
10669 worldmaxs[0] = worldorigin[0] + worldsize;
10670 worldmaxs[1] = worldorigin[1] + worldsize;
10671 worldmaxs[2] = worldorigin[2] + worldsize;
10673 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10675 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10677 ent = r_refdef.scene.entities[renderentityindex];
10678 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10681 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10685 typedef struct r_decalsystem_splatqueue_s
10687 vec3_t worldorigin;
10688 vec3_t worldnormal;
10694 r_decalsystem_splatqueue_t;
10696 int r_decalsystem_numqueued = 0;
10697 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10699 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)
10701 r_decalsystem_splatqueue_t *queue;
10703 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10706 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10707 VectorCopy(worldorigin, queue->worldorigin);
10708 VectorCopy(worldnormal, queue->worldnormal);
10709 Vector4Set(queue->color, r, g, b, a);
10710 Vector4Set(queue->tcrange, s1, t1, s2, t2);
10711 queue->worldsize = worldsize;
10712 queue->decalsequence = cl.decalsequence++;
10715 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10718 r_decalsystem_splatqueue_t *queue;
10720 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10721 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);
10722 r_decalsystem_numqueued = 0;
10725 extern cvar_t cl_decals_max;
10726 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10729 decalsystem_t *decalsystem = &ent->decalsystem;
10736 if (!decalsystem->numdecals)
10739 if (r_showsurfaces.integer)
10742 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10744 R_DecalSystem_Reset(decalsystem);
10748 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10749 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10751 if (decalsystem->lastupdatetime)
10752 frametime = (cl.time - decalsystem->lastupdatetime);
10755 decalsystem->lastupdatetime = cl.time;
10756 decal = decalsystem->decals;
10757 numdecals = decalsystem->numdecals;
10759 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10761 if (decal->color4f[0][3])
10763 decal->lived += frametime;
10764 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10766 memset(decal, 0, sizeof(*decal));
10767 if (decalsystem->freedecal > i)
10768 decalsystem->freedecal = i;
10772 decal = decalsystem->decals;
10773 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10776 // collapse the array by shuffling the tail decals into the gaps
10779 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10780 decalsystem->freedecal++;
10781 if (decalsystem->freedecal == numdecals)
10783 decal[decalsystem->freedecal] = decal[--numdecals];
10786 decalsystem->numdecals = numdecals;
10788 if (numdecals <= 0)
10790 // if there are no decals left, reset decalsystem
10791 R_DecalSystem_Reset(decalsystem);
10795 extern skinframe_t *decalskinframe;
10796 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10799 decalsystem_t *decalsystem = &ent->decalsystem;
10808 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10811 numdecals = decalsystem->numdecals;
10815 if (r_showsurfaces.integer)
10818 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10820 R_DecalSystem_Reset(decalsystem);
10824 // if the model is static it doesn't matter what value we give for
10825 // wantnormals and wanttangents, so this logic uses only rules applicable
10826 // to a model, knowing that they are meaningless otherwise
10827 if (ent == r_refdef.scene.worldentity)
10828 RSurf_ActiveWorldEntity();
10830 RSurf_ActiveModelEntity(ent, false, false, false);
10832 decalsystem->lastupdatetime = cl.time;
10833 decal = decalsystem->decals;
10835 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10837 // update vertex positions for animated models
10838 v3f = decalsystem->vertex3f;
10839 c4f = decalsystem->color4f;
10840 t2f = decalsystem->texcoord2f;
10841 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10843 if (!decal->color4f[0][3])
10846 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10849 // update color values for fading decals
10850 if (decal->lived >= cl_decals_time.value)
10851 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10855 c4f[ 0] = decal->color4f[0][0] * alpha;
10856 c4f[ 1] = decal->color4f[0][1] * alpha;
10857 c4f[ 2] = decal->color4f[0][2] * alpha;
10859 c4f[ 4] = decal->color4f[1][0] * alpha;
10860 c4f[ 5] = decal->color4f[1][1] * alpha;
10861 c4f[ 6] = decal->color4f[1][2] * alpha;
10863 c4f[ 8] = decal->color4f[2][0] * alpha;
10864 c4f[ 9] = decal->color4f[2][1] * alpha;
10865 c4f[10] = decal->color4f[2][2] * alpha;
10868 t2f[0] = decal->texcoord2f[0][0];
10869 t2f[1] = decal->texcoord2f[0][1];
10870 t2f[2] = decal->texcoord2f[1][0];
10871 t2f[3] = decal->texcoord2f[1][1];
10872 t2f[4] = decal->texcoord2f[2][0];
10873 t2f[5] = decal->texcoord2f[2][1];
10875 // update vertex positions for animated models
10876 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10878 e = rsurface.modelelement3i + 3*decal->triangleindex;
10879 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10880 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10881 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10885 VectorCopy(decal->vertex3f[0], v3f);
10886 VectorCopy(decal->vertex3f[1], v3f + 3);
10887 VectorCopy(decal->vertex3f[2], v3f + 6);
10890 if (r_refdef.fogenabled)
10892 alpha = RSurf_FogVertex(v3f);
10893 VectorScale(c4f, alpha, c4f);
10894 alpha = RSurf_FogVertex(v3f + 3);
10895 VectorScale(c4f + 4, alpha, c4f + 4);
10896 alpha = RSurf_FogVertex(v3f + 6);
10897 VectorScale(c4f + 8, alpha, c4f + 8);
10908 r_refdef.stats.drawndecals += numtris;
10910 // now render the decals all at once
10911 // (this assumes they all use one particle font texture!)
10912 RSurf_ActiveCustomEntity(&rsurface.matrix, &rsurface.inversematrix, rsurface.ent_flags, rsurface.ent_shadertime, 1, 1, 1, 1, numdecals*3, decalsystem->vertex3f, decalsystem->texcoord2f, NULL, NULL, NULL, decalsystem->color4f, numtris, decalsystem->element3i, decalsystem->element3s, false, false);
10913 // R_Mesh_ResetTextureState();
10914 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10915 GL_DepthMask(false);
10916 GL_DepthRange(0, 1);
10917 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10918 GL_DepthTest(true);
10919 GL_CullFace(GL_NONE);
10920 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10921 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10922 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10926 static void R_DrawModelDecals(void)
10930 // fade faster when there are too many decals
10931 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10932 for (i = 0;i < r_refdef.scene.numentities;i++)
10933 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10935 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10936 for (i = 0;i < r_refdef.scene.numentities;i++)
10937 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10938 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10940 R_DecalSystem_ApplySplatEntitiesQueue();
10942 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10943 for (i = 0;i < r_refdef.scene.numentities;i++)
10944 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10946 r_refdef.stats.totaldecals += numdecals;
10948 if (r_showsurfaces.integer)
10951 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10953 for (i = 0;i < r_refdef.scene.numentities;i++)
10955 if (!r_refdef.viewcache.entityvisible[i])
10957 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10958 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10962 extern cvar_t mod_collision_bih;
10963 void R_DrawDebugModel(void)
10965 entity_render_t *ent = rsurface.entity;
10966 int i, j, k, l, flagsmask;
10967 const msurface_t *surface;
10968 dp_model_t *model = ent->model;
10971 switch(vid.renderpath)
10973 case RENDERPATH_GL11:
10974 case RENDERPATH_GL13:
10975 case RENDERPATH_GL20:
10977 case RENDERPATH_D3D9:
10978 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10980 case RENDERPATH_D3D10:
10981 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10983 case RENDERPATH_D3D11:
10984 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10986 case RENDERPATH_SOFT:
10987 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10989 case RENDERPATH_GLES2:
10990 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10994 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
10996 // R_Mesh_ResetTextureState();
10997 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10998 GL_DepthRange(0, 1);
10999 GL_DepthTest(!r_showdisabledepthtest.integer);
11000 GL_DepthMask(false);
11001 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11003 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11007 qboolean cullbox = ent == r_refdef.scene.worldentity;
11008 const q3mbrush_t *brush;
11009 const bih_t *bih = &model->collision_bih;
11010 const bih_leaf_t *bihleaf;
11011 float vertex3f[3][3];
11012 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11014 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11016 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11018 switch (bihleaf->type)
11021 brush = model->brush.data_brushes + bihleaf->itemindex;
11022 if (brush->colbrushf && brush->colbrushf->numtriangles)
11024 GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
11025 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11026 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11029 case BIH_COLLISIONTRIANGLE:
11030 triangleindex = bihleaf->itemindex;
11031 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11032 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11033 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11034 GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
11035 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11036 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11038 case BIH_RENDERTRIANGLE:
11039 triangleindex = bihleaf->itemindex;
11040 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11041 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11042 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11043 GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
11044 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11045 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11051 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11053 if (r_showtris.integer || (r_shownormals.value != 0))
11055 if (r_showdisabledepthtest.integer)
11057 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11058 GL_DepthMask(false);
11062 GL_BlendFunc(GL_ONE, GL_ZERO);
11063 GL_DepthMask(true);
11065 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11067 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11069 rsurface.texture = R_GetCurrentTexture(surface->texture);
11070 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11072 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11073 if (r_showtris.value > 0)
11075 if (!rsurface.texture->currentlayers->depthmask)
11076 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11077 else if (ent == r_refdef.scene.worldentity)
11078 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11080 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11081 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11082 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
11084 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
11087 if (r_shownormals.value < 0)
11089 qglBegin(GL_LINES);
11090 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11092 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11093 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11094 qglVertex3f(v[0], v[1], v[2]);
11095 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11096 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11097 qglVertex3f(v[0], v[1], v[2]);
11102 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11104 qglBegin(GL_LINES);
11105 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11107 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11108 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11109 qglVertex3f(v[0], v[1], v[2]);
11110 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11111 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11112 qglVertex3f(v[0], v[1], v[2]);
11116 qglBegin(GL_LINES);
11117 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11119 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11120 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11121 qglVertex3f(v[0], v[1], v[2]);
11122 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11123 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11124 qglVertex3f(v[0], v[1], v[2]);
11128 qglBegin(GL_LINES);
11129 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11131 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11132 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11133 qglVertex3f(v[0], v[1], v[2]);
11134 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11135 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11136 qglVertex3f(v[0], v[1], v[2]);
11143 rsurface.texture = NULL;
11147 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11148 int r_maxsurfacelist = 0;
11149 const msurface_t **r_surfacelist = NULL;
11150 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11152 int i, j, endj, flagsmask;
11153 dp_model_t *model = r_refdef.scene.worldmodel;
11154 msurface_t *surfaces;
11155 unsigned char *update;
11156 int numsurfacelist = 0;
11160 if (r_maxsurfacelist < model->num_surfaces)
11162 r_maxsurfacelist = model->num_surfaces;
11164 Mem_Free((msurface_t**)r_surfacelist);
11165 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11168 RSurf_ActiveWorldEntity();
11170 surfaces = model->data_surfaces;
11171 update = model->brushq1.lightmapupdateflags;
11173 // update light styles on this submodel
11174 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11176 model_brush_lightstyleinfo_t *style;
11177 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11179 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11181 int *list = style->surfacelist;
11182 style->value = r_refdef.scene.lightstylevalue[style->style];
11183 for (j = 0;j < style->numsurfaces;j++)
11184 update[list[j]] = true;
11189 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11193 R_DrawDebugModel();
11194 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11198 rsurface.lightmaptexture = NULL;
11199 rsurface.deluxemaptexture = NULL;
11200 rsurface.uselightmaptexture = false;
11201 rsurface.texture = NULL;
11202 rsurface.rtlight = NULL;
11203 numsurfacelist = 0;
11204 // add visible surfaces to draw list
11205 for (i = 0;i < model->nummodelsurfaces;i++)
11207 j = model->sortedmodelsurfaces[i];
11208 if (r_refdef.viewcache.world_surfacevisible[j])
11209 r_surfacelist[numsurfacelist++] = surfaces + j;
11211 // update lightmaps if needed
11212 if (model->brushq1.firstrender)
11214 model->brushq1.firstrender = false;
11215 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11217 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11221 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11222 if (r_refdef.viewcache.world_surfacevisible[j])
11224 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11226 // don't do anything if there were no surfaces
11227 if (!numsurfacelist)
11229 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11232 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11234 // add to stats if desired
11235 if (r_speeds.integer && !skysurfaces && !depthonly)
11237 r_refdef.stats.world_surfaces += numsurfacelist;
11238 for (j = 0;j < numsurfacelist;j++)
11239 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11242 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11245 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11247 int i, j, endj, flagsmask;
11248 dp_model_t *model = ent->model;
11249 msurface_t *surfaces;
11250 unsigned char *update;
11251 int numsurfacelist = 0;
11255 if (r_maxsurfacelist < model->num_surfaces)
11257 r_maxsurfacelist = model->num_surfaces;
11259 Mem_Free((msurface_t **)r_surfacelist);
11260 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11263 // if the model is static it doesn't matter what value we give for
11264 // wantnormals and wanttangents, so this logic uses only rules applicable
11265 // to a model, knowing that they are meaningless otherwise
11266 if (ent == r_refdef.scene.worldentity)
11267 RSurf_ActiveWorldEntity();
11268 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11269 RSurf_ActiveModelEntity(ent, false, false, false);
11271 RSurf_ActiveModelEntity(ent, true, true, true);
11272 else if (depthonly)
11274 switch (vid.renderpath)
11276 case RENDERPATH_GL20:
11277 case RENDERPATH_D3D9:
11278 case RENDERPATH_D3D10:
11279 case RENDERPATH_D3D11:
11280 case RENDERPATH_SOFT:
11281 case RENDERPATH_GLES2:
11282 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11284 case RENDERPATH_GL13:
11285 case RENDERPATH_GL11:
11286 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11292 switch (vid.renderpath)
11294 case RENDERPATH_GL20:
11295 case RENDERPATH_D3D9:
11296 case RENDERPATH_D3D10:
11297 case RENDERPATH_D3D11:
11298 case RENDERPATH_SOFT:
11299 case RENDERPATH_GLES2:
11300 RSurf_ActiveModelEntity(ent, true, true, false);
11302 case RENDERPATH_GL13:
11303 case RENDERPATH_GL11:
11304 RSurf_ActiveModelEntity(ent, true, false, false);
11309 surfaces = model->data_surfaces;
11310 update = model->brushq1.lightmapupdateflags;
11312 // update light styles
11313 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11315 model_brush_lightstyleinfo_t *style;
11316 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11318 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11320 int *list = style->surfacelist;
11321 style->value = r_refdef.scene.lightstylevalue[style->style];
11322 for (j = 0;j < style->numsurfaces;j++)
11323 update[list[j]] = true;
11328 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11332 R_DrawDebugModel();
11333 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11337 rsurface.lightmaptexture = NULL;
11338 rsurface.deluxemaptexture = NULL;
11339 rsurface.uselightmaptexture = false;
11340 rsurface.texture = NULL;
11341 rsurface.rtlight = NULL;
11342 numsurfacelist = 0;
11343 // add visible surfaces to draw list
11344 for (i = 0;i < model->nummodelsurfaces;i++)
11345 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11346 // don't do anything if there were no surfaces
11347 if (!numsurfacelist)
11349 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11352 // update lightmaps if needed
11356 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11361 R_BuildLightMap(ent, surfaces + j);
11366 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11368 R_BuildLightMap(ent, surfaces + j);
11369 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11371 // add to stats if desired
11372 if (r_speeds.integer && !skysurfaces && !depthonly)
11374 r_refdef.stats.entities_surfaces += numsurfacelist;
11375 for (j = 0;j < numsurfacelist;j++)
11376 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11379 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11382 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11384 static texture_t texture;
11385 static msurface_t surface;
11386 const msurface_t *surfacelist = &surface;
11388 // fake enough texture and surface state to render this geometry
11390 texture.update_lastrenderframe = -1; // regenerate this texture
11391 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11392 texture.currentskinframe = skinframe;
11393 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11394 texture.offsetmapping = OFFSETMAPPING_OFF;
11395 texture.offsetscale = 1;
11396 texture.specularscalemod = 1;
11397 texture.specularpowermod = 1;
11399 surface.texture = &texture;
11400 surface.num_triangles = numtriangles;
11401 surface.num_firsttriangle = firsttriangle;
11402 surface.num_vertices = numvertices;
11403 surface.num_firstvertex = firstvertex;
11406 rsurface.texture = R_GetCurrentTexture(surface.texture);
11407 rsurface.lightmaptexture = NULL;
11408 rsurface.deluxemaptexture = NULL;
11409 rsurface.uselightmaptexture = false;
11410 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11413 void R_DrawCustomSurface_Texture(texture_t *texture, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11415 static msurface_t surface;
11416 const msurface_t *surfacelist = &surface;
11418 // fake enough texture and surface state to render this geometry
11419 surface.texture = texture;
11420 surface.num_triangles = numtriangles;
11421 surface.num_firsttriangle = firsttriangle;
11422 surface.num_vertices = numvertices;
11423 surface.num_firstvertex = firstvertex;
11426 rsurface.texture = R_GetCurrentTexture(surface.texture);
11427 rsurface.lightmaptexture = NULL;
11428 rsurface.deluxemaptexture = NULL;
11429 rsurface.uselightmaptexture = false;
11430 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);