2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "cl_dyntexture.h"
30 #include "dpsoftrast.h"
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
55 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
56 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
57 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
58 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
60 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
62 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
63 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
64 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
65 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
66 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
68 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
69 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
70 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
71 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
72 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
73 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
74 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
75 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
76 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
77 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
78 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
79 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
80 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
81 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
82 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
83 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
84 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
85 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
86 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
87 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
88 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
89 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
90 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
91 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
92 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
93 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
94 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
95 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
97 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
98 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
99 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
101 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
102 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
103 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
104 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
105 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
106 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
107 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
108 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
109 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
110 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
111 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
112 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
113 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
114 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
115 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
116 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
117 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
118 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
119 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
120 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
122 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
123 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
124 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
125 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
126 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
127 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
128 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
129 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
131 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
132 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
134 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
135 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
136 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
137 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
138 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
140 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
141 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
142 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
144 cvar_t r_viewfbo = {CVAR_SAVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"};
145 cvar_t r_viewscale = {CVAR_SAVE, "r_viewscale", "1", "scaling factor for resolution of the fbo rendering method, must be > 0, can be above 1 for a costly antialiasing behavior, typical values are 0.5 for 1/4th as many pixels rendered, or 1 for normal rendering"};
146 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
147 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.25", "worst acceptable quality"};
148 cvar_t r_viewscale_fpsscaling_multiply = {CVAR_SAVE, "r_viewscale_fpsscaling_multiply", "5", "adjust quality up or down by the frametime difference from 1.0/target, multiplied by this factor"};
149 cvar_t r_viewscale_fpsscaling_stepsize = {CVAR_SAVE, "r_viewscale_fpsscaling_stepsize", "0.01", "smallest adjustment to hit the target framerate (this value prevents minute oscillations)"};
150 cvar_t r_viewscale_fpsscaling_stepmax = {CVAR_SAVE, "r_viewscale_fpsscaling_stepmax", "1.00", "largest adjustment to hit the target framerate (this value prevents wild overshooting of the estimate)"};
151 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "90", "desired framerate"};
153 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
154 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
155 cvar_t r_glsl_offsetmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
156 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
157 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
158 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
159 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
160 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
161 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
162 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
163 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
164 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
165 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
166 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
167 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
169 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
170 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
171 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
172 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
173 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
174 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
176 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
177 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
178 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
179 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
181 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
182 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
183 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
184 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
185 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
186 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
187 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
189 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
190 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
191 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
192 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivalent to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
193 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
194 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
195 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
196 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
197 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
198 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
200 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
202 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
204 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
206 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
207 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
208 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
209 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
210 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
211 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
212 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "15", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
213 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
214 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
216 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
217 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
219 cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer."};
221 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
223 extern cvar_t v_glslgamma;
225 extern qboolean v_flipped_state;
227 static struct r_bloomstate_s
232 int bloomwidth, bloomheight;
234 textype_t texturetype;
235 int viewfbo; // used to check if r_viewfbo cvar has changed
237 int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
238 rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
239 rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
241 int screentexturewidth, screentextureheight;
242 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
244 int bloomtexturewidth, bloomtextureheight;
245 rtexture_t *texture_bloom;
247 // arrays for rendering the screen passes
248 float screentexcoord2f[8];
249 float bloomtexcoord2f[8];
250 float offsettexcoord2f[8];
252 r_viewport_t viewport;
256 r_waterstate_t r_waterstate;
258 /// shadow volume bsp struct with automatically growing nodes buffer
261 rtexture_t *r_texture_blanknormalmap;
262 rtexture_t *r_texture_white;
263 rtexture_t *r_texture_grey128;
264 rtexture_t *r_texture_black;
265 rtexture_t *r_texture_notexture;
266 rtexture_t *r_texture_whitecube;
267 rtexture_t *r_texture_normalizationcube;
268 rtexture_t *r_texture_fogattenuation;
269 rtexture_t *r_texture_fogheighttexture;
270 rtexture_t *r_texture_gammaramps;
271 unsigned int r_texture_gammaramps_serial;
272 //rtexture_t *r_texture_fogintensity;
273 rtexture_t *r_texture_reflectcube;
275 // TODO: hash lookups?
276 typedef struct cubemapinfo_s
283 int r_texture_numcubemaps;
284 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
286 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
287 unsigned int r_numqueries;
288 unsigned int r_maxqueries;
290 typedef struct r_qwskincache_s
292 char name[MAX_QPATH];
293 skinframe_t *skinframe;
297 static r_qwskincache_t *r_qwskincache;
298 static int r_qwskincache_size;
300 /// vertex coordinates for a quad that covers the screen exactly
301 extern const float r_screenvertex3f[12];
302 extern const float r_d3dscreenvertex3f[12];
303 const float r_screenvertex3f[12] =
310 const float r_d3dscreenvertex3f[12] =
318 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
321 for (i = 0;i < verts;i++)
332 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
335 for (i = 0;i < verts;i++)
345 // FIXME: move this to client?
348 if (gamemode == GAME_NEHAHRA)
350 Cvar_Set("gl_fogenable", "0");
351 Cvar_Set("gl_fogdensity", "0.2");
352 Cvar_Set("gl_fogred", "0.3");
353 Cvar_Set("gl_foggreen", "0.3");
354 Cvar_Set("gl_fogblue", "0.3");
356 r_refdef.fog_density = 0;
357 r_refdef.fog_red = 0;
358 r_refdef.fog_green = 0;
359 r_refdef.fog_blue = 0;
360 r_refdef.fog_alpha = 1;
361 r_refdef.fog_start = 0;
362 r_refdef.fog_end = 16384;
363 r_refdef.fog_height = 1<<30;
364 r_refdef.fog_fadedepth = 128;
365 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
368 static void R_BuildBlankTextures(void)
370 unsigned char data[4];
371 data[2] = 128; // normal X
372 data[1] = 128; // normal Y
373 data[0] = 255; // normal Z
374 data[3] = 128; // height
375 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
380 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
385 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
390 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
393 static void R_BuildNoTexture(void)
396 unsigned char pix[16][16][4];
397 // this makes a light grey/dark grey checkerboard texture
398 for (y = 0;y < 16;y++)
400 for (x = 0;x < 16;x++)
402 if ((y < 8) ^ (x < 8))
418 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
421 static void R_BuildWhiteCube(void)
423 unsigned char data[6*1*1*4];
424 memset(data, 255, sizeof(data));
425 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
428 static void R_BuildNormalizationCube(void)
432 vec_t s, t, intensity;
435 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
436 for (side = 0;side < 6;side++)
438 for (y = 0;y < NORMSIZE;y++)
440 for (x = 0;x < NORMSIZE;x++)
442 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
443 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
478 intensity = 127.0f / sqrt(DotProduct(v, v));
479 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
480 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
481 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
482 data[((side*64+y)*64+x)*4+3] = 255;
486 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
490 static void R_BuildFogTexture(void)
494 unsigned char data1[FOGWIDTH][4];
495 //unsigned char data2[FOGWIDTH][4];
498 r_refdef.fogmasktable_start = r_refdef.fog_start;
499 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
500 r_refdef.fogmasktable_range = r_refdef.fogrange;
501 r_refdef.fogmasktable_density = r_refdef.fog_density;
503 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
504 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
506 d = (x * r - r_refdef.fogmasktable_start);
507 if(developer_extra.integer)
508 Con_DPrintf("%f ", d);
510 if (r_fog_exp2.integer)
511 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
513 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
514 if(developer_extra.integer)
515 Con_DPrintf(" : %f ", alpha);
516 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
517 if(developer_extra.integer)
518 Con_DPrintf(" = %f\n", alpha);
519 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
522 for (x = 0;x < FOGWIDTH;x++)
524 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
529 //data2[x][0] = 255 - b;
530 //data2[x][1] = 255 - b;
531 //data2[x][2] = 255 - b;
534 if (r_texture_fogattenuation)
536 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
537 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
541 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
542 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
546 static void R_BuildFogHeightTexture(void)
548 unsigned char *inpixels;
556 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
557 if (r_refdef.fogheighttexturename[0])
558 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
561 r_refdef.fog_height_tablesize = 0;
562 if (r_texture_fogheighttexture)
563 R_FreeTexture(r_texture_fogheighttexture);
564 r_texture_fogheighttexture = NULL;
565 if (r_refdef.fog_height_table2d)
566 Mem_Free(r_refdef.fog_height_table2d);
567 r_refdef.fog_height_table2d = NULL;
568 if (r_refdef.fog_height_table1d)
569 Mem_Free(r_refdef.fog_height_table1d);
570 r_refdef.fog_height_table1d = NULL;
574 r_refdef.fog_height_tablesize = size;
575 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
576 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
577 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
579 // LordHavoc: now the magic - what is that table2d for? it is a cooked
580 // average fog color table accounting for every fog layer between a point
581 // and the camera. (Note: attenuation is handled separately!)
582 for (y = 0;y < size;y++)
584 for (x = 0;x < size;x++)
590 for (j = x;j <= y;j++)
592 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
598 for (j = x;j >= y;j--)
600 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
605 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
606 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
607 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
608 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
611 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
614 //=======================================================================================================================================================
616 static const char *builtinshaderstring =
617 #include "shader_glsl.h"
620 const char *builtinhlslshaderstring =
621 #include "shader_hlsl.h"
624 char *glslshaderstring = NULL;
625 char *hlslshaderstring = NULL;
627 //=======================================================================================================================================================
629 typedef struct shaderpermutationinfo_s
634 shaderpermutationinfo_t;
636 typedef struct shadermodeinfo_s
638 const char *vertexfilename;
639 const char *geometryfilename;
640 const char *fragmentfilename;
646 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
647 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
649 {"#define USEDIFFUSE\n", " diffuse"},
650 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
651 {"#define USEVIEWTINT\n", " viewtint"},
652 {"#define USECOLORMAPPING\n", " colormapping"},
653 {"#define USESATURATION\n", " saturation"},
654 {"#define USEFOGINSIDE\n", " foginside"},
655 {"#define USEFOGOUTSIDE\n", " fogoutside"},
656 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
657 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
658 {"#define USEGAMMARAMPS\n", " gammaramps"},
659 {"#define USECUBEFILTER\n", " cubefilter"},
660 {"#define USEGLOW\n", " glow"},
661 {"#define USEBLOOM\n", " bloom"},
662 {"#define USESPECULAR\n", " specular"},
663 {"#define USEPOSTPROCESSING\n", " postprocessing"},
664 {"#define USEREFLECTION\n", " reflection"},
665 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
666 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
667 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
668 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
669 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
670 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
671 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
672 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
673 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
674 {"#define USEALPHAKILL\n", " alphakill"},
675 {"#define USEREFLECTCUBE\n", " reflectcube"},
676 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
677 {"#define USEBOUNCEGRID\n", " bouncegrid"},
678 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
681 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
682 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
684 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
685 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
686 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
687 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
688 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
689 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
690 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
691 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
692 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
693 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
694 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
695 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
696 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
697 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
698 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
699 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
702 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
704 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
705 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
706 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
707 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
708 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
709 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
710 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
711 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
712 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
713 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
714 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
715 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
716 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
717 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
718 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
719 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
722 struct r_glsl_permutation_s;
723 typedef struct r_glsl_permutation_s
726 struct r_glsl_permutation_s *hashnext;
728 unsigned int permutation;
730 /// indicates if we have tried compiling this permutation already
732 /// 0 if compilation failed
734 // texture units assigned to each detected uniform
735 int tex_Texture_First;
736 int tex_Texture_Second;
737 int tex_Texture_GammaRamps;
738 int tex_Texture_Normal;
739 int tex_Texture_Color;
740 int tex_Texture_Gloss;
741 int tex_Texture_Glow;
742 int tex_Texture_SecondaryNormal;
743 int tex_Texture_SecondaryColor;
744 int tex_Texture_SecondaryGloss;
745 int tex_Texture_SecondaryGlow;
746 int tex_Texture_Pants;
747 int tex_Texture_Shirt;
748 int tex_Texture_FogHeightTexture;
749 int tex_Texture_FogMask;
750 int tex_Texture_Lightmap;
751 int tex_Texture_Deluxemap;
752 int tex_Texture_Attenuation;
753 int tex_Texture_Cube;
754 int tex_Texture_Refraction;
755 int tex_Texture_Reflection;
756 int tex_Texture_ShadowMap2D;
757 int tex_Texture_CubeProjection;
758 int tex_Texture_ScreenDepth;
759 int tex_Texture_ScreenNormalMap;
760 int tex_Texture_ScreenDiffuse;
761 int tex_Texture_ScreenSpecular;
762 int tex_Texture_ReflectMask;
763 int tex_Texture_ReflectCube;
764 int tex_Texture_BounceGrid;
765 /// locations of detected uniforms in program object, or -1 if not found
766 int loc_Texture_First;
767 int loc_Texture_Second;
768 int loc_Texture_GammaRamps;
769 int loc_Texture_Normal;
770 int loc_Texture_Color;
771 int loc_Texture_Gloss;
772 int loc_Texture_Glow;
773 int loc_Texture_SecondaryNormal;
774 int loc_Texture_SecondaryColor;
775 int loc_Texture_SecondaryGloss;
776 int loc_Texture_SecondaryGlow;
777 int loc_Texture_Pants;
778 int loc_Texture_Shirt;
779 int loc_Texture_FogHeightTexture;
780 int loc_Texture_FogMask;
781 int loc_Texture_Lightmap;
782 int loc_Texture_Deluxemap;
783 int loc_Texture_Attenuation;
784 int loc_Texture_Cube;
785 int loc_Texture_Refraction;
786 int loc_Texture_Reflection;
787 int loc_Texture_ShadowMap2D;
788 int loc_Texture_CubeProjection;
789 int loc_Texture_ScreenDepth;
790 int loc_Texture_ScreenNormalMap;
791 int loc_Texture_ScreenDiffuse;
792 int loc_Texture_ScreenSpecular;
793 int loc_Texture_ReflectMask;
794 int loc_Texture_ReflectCube;
795 int loc_Texture_BounceGrid;
797 int loc_BloomBlur_Parameters;
799 int loc_Color_Ambient;
800 int loc_Color_Diffuse;
801 int loc_Color_Specular;
805 int loc_DeferredColor_Ambient;
806 int loc_DeferredColor_Diffuse;
807 int loc_DeferredColor_Specular;
808 int loc_DeferredMod_Diffuse;
809 int loc_DeferredMod_Specular;
810 int loc_DistortScaleRefractReflect;
813 int loc_FogHeightFade;
815 int loc_FogPlaneViewDist;
816 int loc_FogRangeRecip;
819 int loc_LightPosition;
820 int loc_OffsetMapping_ScaleSteps;
822 int loc_ReflectColor;
823 int loc_ReflectFactor;
824 int loc_ReflectOffset;
825 int loc_RefractColor;
827 int loc_ScreenCenterRefractReflect;
828 int loc_ScreenScaleRefractReflect;
829 int loc_ScreenToDepth;
830 int loc_ShadowMap_Parameters;
831 int loc_ShadowMap_TextureScale;
832 int loc_SpecularPower;
837 int loc_ViewTintColor;
839 int loc_ModelToLight;
841 int loc_BackgroundTexMatrix;
842 int loc_ModelViewProjectionMatrix;
843 int loc_ModelViewMatrix;
844 int loc_PixelToScreenTexCoord;
845 int loc_ModelToReflectCube;
846 int loc_ShadowMapMatrix;
847 int loc_BloomColorSubtract;
848 int loc_NormalmapScrollBlend;
849 int loc_BounceGridMatrix;
850 int loc_BounceGridIntensity;
852 r_glsl_permutation_t;
854 #define SHADERPERMUTATION_HASHSIZE 256
857 // non-degradable "lightweight" shader parameters to keep the permutations simpler
858 // these can NOT degrade! only use for simple stuff
861 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
862 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
863 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
864 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
865 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
866 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
867 SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
869 #define SHADERSTATICPARMS_COUNT 7
871 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
872 static int shaderstaticparms_count = 0;
874 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
875 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
876 qboolean R_CompileShader_CheckStaticParms(void)
878 static int r_compileshader_staticparms_save[1];
879 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
880 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
883 if (r_glsl_saturation_redcompensate.integer)
884 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
885 if (r_glsl_vertextextureblend_usebothalphas.integer)
886 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
887 if (r_shadow_glossexact.integer)
888 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
889 if (r_glsl_postprocess.integer)
891 if (r_glsl_postprocess_uservec1_enable.integer)
892 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
893 if (r_glsl_postprocess_uservec2_enable.integer)
894 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
895 if (r_glsl_postprocess_uservec3_enable.integer)
896 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
897 if (r_glsl_postprocess_uservec4_enable.integer)
898 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
900 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
903 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
904 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
905 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
907 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
908 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
910 shaderstaticparms_count = 0;
913 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
914 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
915 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
916 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
917 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
918 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
919 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
922 /// information about each possible shader permutation
923 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
924 /// currently selected permutation
925 r_glsl_permutation_t *r_glsl_permutation;
926 /// storage for permutations linked in the hash table
927 memexpandablearray_t r_glsl_permutationarray;
929 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
931 //unsigned int hashdepth = 0;
932 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
933 r_glsl_permutation_t *p;
934 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
936 if (p->mode == mode && p->permutation == permutation)
938 //if (hashdepth > 10)
939 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
944 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
946 p->permutation = permutation;
947 p->hashnext = r_glsl_permutationhash[mode][hashindex];
948 r_glsl_permutationhash[mode][hashindex] = p;
949 //if (hashdepth > 10)
950 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
954 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
957 if (!filename || !filename[0])
959 if (!strcmp(filename, "glsl/default.glsl"))
961 if (!glslshaderstring)
963 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
964 if (glslshaderstring)
965 Con_DPrintf("Loading shaders from file %s...\n", filename);
967 glslshaderstring = (char *)builtinshaderstring;
969 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
970 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
973 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
976 if (printfromdisknotice)
977 Con_DPrintf("from disk %s... ", filename);
983 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
987 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
988 char *vertexstring, *geometrystring, *fragmentstring;
989 char permutationname[256];
990 int vertstrings_count = 0;
991 int geomstrings_count = 0;
992 int fragstrings_count = 0;
993 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
994 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
995 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1002 permutationname[0] = 0;
1003 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1004 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1005 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1007 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1009 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1010 if(vid.support.gl20shaders130)
1012 vertstrings_list[vertstrings_count++] = "#version 130\n";
1013 geomstrings_list[geomstrings_count++] = "#version 130\n";
1014 fragstrings_list[fragstrings_count++] = "#version 130\n";
1015 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1016 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1017 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1020 // the first pretext is which type of shader to compile as
1021 // (later these will all be bound together as a program object)
1022 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1023 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1024 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1026 // the second pretext is the mode (for example a light source)
1027 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1028 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1029 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1030 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1032 // now add all the permutation pretexts
1033 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1035 if (permutation & (1<<i))
1037 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1038 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1039 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1040 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1044 // keep line numbers correct
1045 vertstrings_list[vertstrings_count++] = "\n";
1046 geomstrings_list[geomstrings_count++] = "\n";
1047 fragstrings_list[fragstrings_count++] = "\n";
1052 R_CompileShader_AddStaticParms(mode, permutation);
1053 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1054 vertstrings_count += shaderstaticparms_count;
1055 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1056 geomstrings_count += shaderstaticparms_count;
1057 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1058 fragstrings_count += shaderstaticparms_count;
1060 // now append the shader text itself
1061 vertstrings_list[vertstrings_count++] = vertexstring;
1062 geomstrings_list[geomstrings_count++] = geometrystring;
1063 fragstrings_list[fragstrings_count++] = fragmentstring;
1065 // if any sources were NULL, clear the respective list
1067 vertstrings_count = 0;
1068 if (!geometrystring)
1069 geomstrings_count = 0;
1070 if (!fragmentstring)
1071 fragstrings_count = 0;
1073 // compile the shader program
1074 if (vertstrings_count + geomstrings_count + fragstrings_count)
1075 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1079 qglUseProgram(p->program);CHECKGLERROR
1080 // look up all the uniform variable names we care about, so we don't
1081 // have to look them up every time we set them
1083 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1084 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1085 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1086 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1087 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1088 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1089 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1090 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1091 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1092 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1093 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1094 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1095 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1096 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1097 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1098 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1099 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1100 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1101 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1102 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1103 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1104 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1105 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1106 p->loc_Texture_ScreenDepth = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1107 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1108 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1109 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1110 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1111 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1112 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1113 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1114 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1115 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1116 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1117 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1118 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1119 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1120 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1121 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1122 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1123 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1124 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1125 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1126 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1127 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1128 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1129 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1130 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1131 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1132 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1133 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1134 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1135 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1136 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1137 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1138 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1139 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1140 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1141 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1142 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1143 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1144 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1145 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1146 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1147 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1148 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1149 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1150 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1151 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1152 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1153 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1154 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1155 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1156 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1157 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1158 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1159 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1160 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1161 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1162 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1163 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1164 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1165 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1166 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1167 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1168 // initialize the samplers to refer to the texture units we use
1169 p->tex_Texture_First = -1;
1170 p->tex_Texture_Second = -1;
1171 p->tex_Texture_GammaRamps = -1;
1172 p->tex_Texture_Normal = -1;
1173 p->tex_Texture_Color = -1;
1174 p->tex_Texture_Gloss = -1;
1175 p->tex_Texture_Glow = -1;
1176 p->tex_Texture_SecondaryNormal = -1;
1177 p->tex_Texture_SecondaryColor = -1;
1178 p->tex_Texture_SecondaryGloss = -1;
1179 p->tex_Texture_SecondaryGlow = -1;
1180 p->tex_Texture_Pants = -1;
1181 p->tex_Texture_Shirt = -1;
1182 p->tex_Texture_FogHeightTexture = -1;
1183 p->tex_Texture_FogMask = -1;
1184 p->tex_Texture_Lightmap = -1;
1185 p->tex_Texture_Deluxemap = -1;
1186 p->tex_Texture_Attenuation = -1;
1187 p->tex_Texture_Cube = -1;
1188 p->tex_Texture_Refraction = -1;
1189 p->tex_Texture_Reflection = -1;
1190 p->tex_Texture_ShadowMap2D = -1;
1191 p->tex_Texture_CubeProjection = -1;
1192 p->tex_Texture_ScreenDepth = -1;
1193 p->tex_Texture_ScreenNormalMap = -1;
1194 p->tex_Texture_ScreenDiffuse = -1;
1195 p->tex_Texture_ScreenSpecular = -1;
1196 p->tex_Texture_ReflectMask = -1;
1197 p->tex_Texture_ReflectCube = -1;
1198 p->tex_Texture_BounceGrid = -1;
1200 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1201 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1202 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1203 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1204 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1205 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1206 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1207 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1208 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1209 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1210 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1211 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1212 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1213 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1214 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1215 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1216 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1217 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1218 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1219 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1220 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1221 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1222 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1223 if (p->loc_Texture_ScreenDepth >= 0) {p->tex_Texture_ScreenDepth = sampler;qglUniform1i(p->loc_Texture_ScreenDepth , sampler);sampler++;}
1224 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1225 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1226 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1227 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1228 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1229 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1231 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1234 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1238 Mem_Free(vertexstring);
1240 Mem_Free(geometrystring);
1242 Mem_Free(fragmentstring);
1245 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1247 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1248 if (r_glsl_permutation != perm)
1250 r_glsl_permutation = perm;
1251 if (!r_glsl_permutation->program)
1253 if (!r_glsl_permutation->compiled)
1254 R_GLSL_CompilePermutation(perm, mode, permutation);
1255 if (!r_glsl_permutation->program)
1257 // remove features until we find a valid permutation
1259 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1261 // reduce i more quickly whenever it would not remove any bits
1262 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1263 if (!(permutation & j))
1266 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1267 if (!r_glsl_permutation->compiled)
1268 R_GLSL_CompilePermutation(perm, mode, permutation);
1269 if (r_glsl_permutation->program)
1272 if (i >= SHADERPERMUTATION_COUNT)
1274 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1275 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1276 qglUseProgram(0);CHECKGLERROR
1277 return; // no bit left to clear, entire mode is broken
1282 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1284 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1285 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1286 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1293 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1294 extern D3DCAPS9 vid_d3d9caps;
1297 struct r_hlsl_permutation_s;
1298 typedef struct r_hlsl_permutation_s
1300 /// hash lookup data
1301 struct r_hlsl_permutation_s *hashnext;
1303 unsigned int permutation;
1305 /// indicates if we have tried compiling this permutation already
1307 /// NULL if compilation failed
1308 IDirect3DVertexShader9 *vertexshader;
1309 IDirect3DPixelShader9 *pixelshader;
1311 r_hlsl_permutation_t;
1313 typedef enum D3DVSREGISTER_e
1315 D3DVSREGISTER_TexMatrix = 0, // float4x4
1316 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1317 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1318 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1319 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1320 D3DVSREGISTER_ModelToLight = 20, // float4x4
1321 D3DVSREGISTER_EyePosition = 24,
1322 D3DVSREGISTER_FogPlane = 25,
1323 D3DVSREGISTER_LightDir = 26,
1324 D3DVSREGISTER_LightPosition = 27,
1328 typedef enum D3DPSREGISTER_e
1330 D3DPSREGISTER_Alpha = 0,
1331 D3DPSREGISTER_BloomBlur_Parameters = 1,
1332 D3DPSREGISTER_ClientTime = 2,
1333 D3DPSREGISTER_Color_Ambient = 3,
1334 D3DPSREGISTER_Color_Diffuse = 4,
1335 D3DPSREGISTER_Color_Specular = 5,
1336 D3DPSREGISTER_Color_Glow = 6,
1337 D3DPSREGISTER_Color_Pants = 7,
1338 D3DPSREGISTER_Color_Shirt = 8,
1339 D3DPSREGISTER_DeferredColor_Ambient = 9,
1340 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1341 D3DPSREGISTER_DeferredColor_Specular = 11,
1342 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1343 D3DPSREGISTER_DeferredMod_Specular = 13,
1344 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1345 D3DPSREGISTER_EyePosition = 15, // unused
1346 D3DPSREGISTER_FogColor = 16,
1347 D3DPSREGISTER_FogHeightFade = 17,
1348 D3DPSREGISTER_FogPlane = 18,
1349 D3DPSREGISTER_FogPlaneViewDist = 19,
1350 D3DPSREGISTER_FogRangeRecip = 20,
1351 D3DPSREGISTER_LightColor = 21,
1352 D3DPSREGISTER_LightDir = 22, // unused
1353 D3DPSREGISTER_LightPosition = 23,
1354 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1355 D3DPSREGISTER_PixelSize = 25,
1356 D3DPSREGISTER_ReflectColor = 26,
1357 D3DPSREGISTER_ReflectFactor = 27,
1358 D3DPSREGISTER_ReflectOffset = 28,
1359 D3DPSREGISTER_RefractColor = 29,
1360 D3DPSREGISTER_Saturation = 30,
1361 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1362 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1363 D3DPSREGISTER_ScreenToDepth = 33,
1364 D3DPSREGISTER_ShadowMap_Parameters = 34,
1365 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1366 D3DPSREGISTER_SpecularPower = 36,
1367 D3DPSREGISTER_UserVec1 = 37,
1368 D3DPSREGISTER_UserVec2 = 38,
1369 D3DPSREGISTER_UserVec3 = 39,
1370 D3DPSREGISTER_UserVec4 = 40,
1371 D3DPSREGISTER_ViewTintColor = 41,
1372 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1373 D3DPSREGISTER_BloomColorSubtract = 43,
1374 D3DPSREGISTER_ViewToLight = 44, // float4x4
1375 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1376 D3DPSREGISTER_NormalmapScrollBlend = 52,
1381 /// information about each possible shader permutation
1382 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1383 /// currently selected permutation
1384 r_hlsl_permutation_t *r_hlsl_permutation;
1385 /// storage for permutations linked in the hash table
1386 memexpandablearray_t r_hlsl_permutationarray;
1388 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1390 //unsigned int hashdepth = 0;
1391 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1392 r_hlsl_permutation_t *p;
1393 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1395 if (p->mode == mode && p->permutation == permutation)
1397 //if (hashdepth > 10)
1398 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1403 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1405 p->permutation = permutation;
1406 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1407 r_hlsl_permutationhash[mode][hashindex] = p;
1408 //if (hashdepth > 10)
1409 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1413 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1416 if (!filename || !filename[0])
1418 if (!strcmp(filename, "hlsl/default.hlsl"))
1420 if (!hlslshaderstring)
1422 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1423 if (hlslshaderstring)
1424 Con_DPrintf("Loading shaders from file %s...\n", filename);
1426 hlslshaderstring = (char *)builtinhlslshaderstring;
1428 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1429 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1430 return shaderstring;
1432 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1435 if (printfromdisknotice)
1436 Con_DPrintf("from disk %s... ", filename);
1437 return shaderstring;
1439 return shaderstring;
1443 //#include <d3dx9shader.h>
1444 //#include <d3dx9mesh.h>
1446 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1448 DWORD *vsbin = NULL;
1449 DWORD *psbin = NULL;
1450 fs_offset_t vsbinsize;
1451 fs_offset_t psbinsize;
1452 // IDirect3DVertexShader9 *vs = NULL;
1453 // IDirect3DPixelShader9 *ps = NULL;
1454 ID3DXBuffer *vslog = NULL;
1455 ID3DXBuffer *vsbuffer = NULL;
1456 ID3DXConstantTable *vsconstanttable = NULL;
1457 ID3DXBuffer *pslog = NULL;
1458 ID3DXBuffer *psbuffer = NULL;
1459 ID3DXConstantTable *psconstanttable = NULL;
1462 char temp[MAX_INPUTLINE];
1463 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1464 qboolean debugshader = gl_paranoid.integer != 0;
1465 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1466 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1469 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1470 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1472 if ((!vsbin && vertstring) || (!psbin && fragstring))
1474 const char* dllnames_d3dx9 [] =
1498 dllhandle_t d3dx9_dll = NULL;
1499 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1500 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1501 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1502 dllfunction_t d3dx9_dllfuncs[] =
1504 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1505 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1506 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1509 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1511 DWORD shaderflags = 0;
1513 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1514 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1515 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1516 if (vertstring && vertstring[0])
1520 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1521 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1522 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1523 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1526 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1529 vsbinsize = vsbuffer->GetBufferSize();
1530 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1531 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1532 vsbuffer->Release();
1536 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1537 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1541 if (fragstring && fragstring[0])
1545 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1546 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1547 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1548 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1551 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1554 psbinsize = psbuffer->GetBufferSize();
1555 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1556 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1557 psbuffer->Release();
1561 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1562 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1566 Sys_UnloadLibrary(&d3dx9_dll);
1569 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1573 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1574 if (FAILED(vsresult))
1575 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1576 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1577 if (FAILED(psresult))
1578 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1580 // free the shader data
1581 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1582 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1585 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1588 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1589 int vertstring_length = 0;
1590 int geomstring_length = 0;
1591 int fragstring_length = 0;
1593 char *vertexstring, *geometrystring, *fragmentstring;
1594 char *vertstring, *geomstring, *fragstring;
1595 char permutationname[256];
1596 char cachename[256];
1597 int vertstrings_count = 0;
1598 int geomstrings_count = 0;
1599 int fragstrings_count = 0;
1600 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1601 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1602 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1607 p->vertexshader = NULL;
1608 p->pixelshader = NULL;
1610 permutationname[0] = 0;
1612 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
1613 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1614 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1616 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1617 strlcat(cachename, "hlsl/", sizeof(cachename));
1619 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1620 vertstrings_count = 0;
1621 geomstrings_count = 0;
1622 fragstrings_count = 0;
1623 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1624 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1625 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1627 // the first pretext is which type of shader to compile as
1628 // (later these will all be bound together as a program object)
1629 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1630 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1631 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1633 // the second pretext is the mode (for example a light source)
1634 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1635 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1636 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1637 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1638 strlcat(cachename, modeinfo->name, sizeof(cachename));
1640 // now add all the permutation pretexts
1641 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1643 if (permutation & (1<<i))
1645 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1646 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1647 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1648 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1649 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1653 // keep line numbers correct
1654 vertstrings_list[vertstrings_count++] = "\n";
1655 geomstrings_list[geomstrings_count++] = "\n";
1656 fragstrings_list[fragstrings_count++] = "\n";
1661 R_CompileShader_AddStaticParms(mode, permutation);
1662 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1663 vertstrings_count += shaderstaticparms_count;
1664 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1665 geomstrings_count += shaderstaticparms_count;
1666 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1667 fragstrings_count += shaderstaticparms_count;
1669 // replace spaces in the cachename with _ characters
1670 for (i = 0;cachename[i];i++)
1671 if (cachename[i] == ' ')
1674 // now append the shader text itself
1675 vertstrings_list[vertstrings_count++] = vertexstring;
1676 geomstrings_list[geomstrings_count++] = geometrystring;
1677 fragstrings_list[fragstrings_count++] = fragmentstring;
1679 // if any sources were NULL, clear the respective list
1681 vertstrings_count = 0;
1682 if (!geometrystring)
1683 geomstrings_count = 0;
1684 if (!fragmentstring)
1685 fragstrings_count = 0;
1687 vertstring_length = 0;
1688 for (i = 0;i < vertstrings_count;i++)
1689 vertstring_length += strlen(vertstrings_list[i]);
1690 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1691 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1692 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1694 geomstring_length = 0;
1695 for (i = 0;i < geomstrings_count;i++)
1696 geomstring_length += strlen(geomstrings_list[i]);
1697 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1698 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1699 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1701 fragstring_length = 0;
1702 for (i = 0;i < fragstrings_count;i++)
1703 fragstring_length += strlen(fragstrings_list[i]);
1704 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1705 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1706 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1708 // try to load the cached shader, or generate one
1709 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1711 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1712 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1714 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1718 Mem_Free(vertstring);
1720 Mem_Free(geomstring);
1722 Mem_Free(fragstring);
1724 Mem_Free(vertexstring);
1726 Mem_Free(geometrystring);
1728 Mem_Free(fragmentstring);
1731 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1732 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1733 static inline void hlslVSSetParameter4f(D3DVSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1734 static inline void hlslVSSetParameter3f(D3DVSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1735 static inline void hlslVSSetParameter2f(D3DVSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1736 static inline void hlslVSSetParameter1f(D3DVSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1738 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1739 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1740 static inline void hlslPSSetParameter4f(D3DPSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1741 static inline void hlslPSSetParameter3f(D3DPSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1742 static inline void hlslPSSetParameter2f(D3DPSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1743 static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1745 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1747 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1748 if (r_hlsl_permutation != perm)
1750 r_hlsl_permutation = perm;
1751 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1753 if (!r_hlsl_permutation->compiled)
1754 R_HLSL_CompilePermutation(perm, mode, permutation);
1755 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1757 // remove features until we find a valid permutation
1759 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1761 // reduce i more quickly whenever it would not remove any bits
1762 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1763 if (!(permutation & j))
1766 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1767 if (!r_hlsl_permutation->compiled)
1768 R_HLSL_CompilePermutation(perm, mode, permutation);
1769 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1772 if (i >= SHADERPERMUTATION_COUNT)
1774 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1775 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1776 return; // no bit left to clear, entire mode is broken
1780 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1781 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1783 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1784 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1785 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1789 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1791 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1792 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1793 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1794 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1797 void R_GLSL_Restart_f(void)
1799 unsigned int i, limit;
1800 if (glslshaderstring && glslshaderstring != builtinshaderstring)
1801 Mem_Free(glslshaderstring);
1802 glslshaderstring = NULL;
1803 if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1804 Mem_Free(hlslshaderstring);
1805 hlslshaderstring = NULL;
1806 switch(vid.renderpath)
1808 case RENDERPATH_D3D9:
1811 r_hlsl_permutation_t *p;
1812 r_hlsl_permutation = NULL;
1813 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1814 for (i = 0;i < limit;i++)
1816 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1818 if (p->vertexshader)
1819 IDirect3DVertexShader9_Release(p->vertexshader);
1821 IDirect3DPixelShader9_Release(p->pixelshader);
1822 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1825 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1829 case RENDERPATH_D3D10:
1830 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1832 case RENDERPATH_D3D11:
1833 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1835 case RENDERPATH_GL20:
1836 case RENDERPATH_GLES2:
1838 r_glsl_permutation_t *p;
1839 r_glsl_permutation = NULL;
1840 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1841 for (i = 0;i < limit;i++)
1843 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1845 GL_Backend_FreeProgram(p->program);
1846 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1849 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1852 case RENDERPATH_GL13:
1853 case RENDERPATH_GL11:
1855 case RENDERPATH_SOFT:
1860 void R_GLSL_DumpShader_f(void)
1865 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1868 FS_Print(file, "/* The engine may define the following macros:\n");
1869 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1870 for (i = 0;i < SHADERMODE_COUNT;i++)
1871 FS_Print(file, glslshadermodeinfo[i].pretext);
1872 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1873 FS_Print(file, shaderpermutationinfo[i].pretext);
1874 FS_Print(file, "*/\n");
1875 FS_Print(file, builtinshaderstring);
1877 Con_Printf("glsl/default.glsl written\n");
1880 Con_Printf("failed to write to glsl/default.glsl\n");
1882 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1885 FS_Print(file, "/* The engine may define the following macros:\n");
1886 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1887 for (i = 0;i < SHADERMODE_COUNT;i++)
1888 FS_Print(file, hlslshadermodeinfo[i].pretext);
1889 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1890 FS_Print(file, shaderpermutationinfo[i].pretext);
1891 FS_Print(file, "*/\n");
1892 FS_Print(file, builtinhlslshaderstring);
1894 Con_Printf("hlsl/default.hlsl written\n");
1897 Con_Printf("failed to write to hlsl/default.hlsl\n");
1900 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1903 texturemode = GL_MODULATE;
1904 switch (vid.renderpath)
1906 case RENDERPATH_D3D9:
1908 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1909 R_Mesh_TexBind(GL20TU_FIRST , first );
1910 R_Mesh_TexBind(GL20TU_SECOND, second);
1913 case RENDERPATH_D3D10:
1914 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1916 case RENDERPATH_D3D11:
1917 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1919 case RENDERPATH_GL20:
1920 case RENDERPATH_GLES2:
1921 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1922 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1923 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1925 case RENDERPATH_GL13:
1926 R_Mesh_TexBind(0, first );
1927 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1928 R_Mesh_TexBind(1, second);
1930 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1932 case RENDERPATH_GL11:
1933 R_Mesh_TexBind(0, first );
1935 case RENDERPATH_SOFT:
1936 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1937 R_Mesh_TexBind(GL20TU_FIRST , first );
1938 R_Mesh_TexBind(GL20TU_SECOND, second);
1943 void R_SetupShader_DepthOrShadow(void)
1945 switch (vid.renderpath)
1947 case RENDERPATH_D3D9:
1949 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1952 case RENDERPATH_D3D10:
1953 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1955 case RENDERPATH_D3D11:
1956 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1958 case RENDERPATH_GL20:
1959 case RENDERPATH_GLES2:
1960 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1962 case RENDERPATH_GL13:
1963 R_Mesh_TexBind(0, 0);
1964 R_Mesh_TexBind(1, 0);
1966 case RENDERPATH_GL11:
1967 R_Mesh_TexBind(0, 0);
1969 case RENDERPATH_SOFT:
1970 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1975 void R_SetupShader_ShowDepth(void)
1977 switch (vid.renderpath)
1979 case RENDERPATH_D3D9:
1981 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1984 case RENDERPATH_D3D10:
1985 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1987 case RENDERPATH_D3D11:
1988 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1990 case RENDERPATH_GL20:
1991 case RENDERPATH_GLES2:
1992 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1994 case RENDERPATH_GL13:
1996 case RENDERPATH_GL11:
1998 case RENDERPATH_SOFT:
1999 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
2004 extern qboolean r_shadow_usingdeferredprepass;
2005 extern cvar_t r_shadow_deferred_8bitrange;
2006 extern rtexture_t *r_shadow_attenuationgradienttexture;
2007 extern rtexture_t *r_shadow_attenuation2dtexture;
2008 extern rtexture_t *r_shadow_attenuation3dtexture;
2009 extern qboolean r_shadow_usingshadowmap2d;
2010 extern qboolean r_shadow_usingshadowmaportho;
2011 extern float r_shadow_shadowmap_texturescale[2];
2012 extern float r_shadow_shadowmap_parameters[4];
2013 extern qboolean r_shadow_shadowmapvsdct;
2014 extern qboolean r_shadow_shadowmapsampler;
2015 extern int r_shadow_shadowmappcf;
2016 extern rtexture_t *r_shadow_shadowmap2dtexture;
2017 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2018 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2019 extern matrix4x4_t r_shadow_shadowmapmatrix;
2020 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2021 extern int r_shadow_prepass_width;
2022 extern int r_shadow_prepass_height;
2023 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2024 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2025 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2026 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2027 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2029 #define BLENDFUNC_ALLOWS_COLORMOD 1
2030 #define BLENDFUNC_ALLOWS_FOG 2
2031 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2032 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2033 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2034 static int R_BlendFuncFlags(int src, int dst)
2038 // a blendfunc allows colormod if:
2039 // a) it can never keep the destination pixel invariant, or
2040 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2041 // this is to prevent unintended side effects from colormod
2043 // a blendfunc allows fog if:
2044 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2045 // this is to prevent unintended side effects from fog
2047 // these checks are the output of fogeval.pl
2049 r |= BLENDFUNC_ALLOWS_COLORMOD;
2050 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2051 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2052 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2053 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2054 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2055 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2056 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2057 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2058 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2059 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2060 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2061 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2062 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2063 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2064 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2065 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2066 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2067 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2068 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2069 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2070 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2075 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane)
2077 // select a permutation of the lighting shader appropriate to this
2078 // combination of texture, entity, light source, and fogging, only use the
2079 // minimum features necessary to avoid wasting rendering time in the
2080 // fragment shader on features that are not being used
2081 unsigned int permutation = 0;
2082 unsigned int mode = 0;
2084 static float dummy_colormod[3] = {1, 1, 1};
2085 float *colormod = rsurface.colormod;
2087 matrix4x4_t tempmatrix;
2088 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2089 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2090 permutation |= SHADERPERMUTATION_ALPHAKILL;
2091 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2092 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2093 if (rsurfacepass == RSURFPASS_BACKGROUND)
2095 // distorted background
2096 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2098 mode = SHADERMODE_WATER;
2099 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2101 // this is the right thing to do for wateralpha
2102 GL_BlendFunc(GL_ONE, GL_ZERO);
2103 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2107 // this is the right thing to do for entity alpha
2108 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2109 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2112 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2114 mode = SHADERMODE_REFRACTION;
2115 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2116 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2120 mode = SHADERMODE_GENERIC;
2121 permutation |= SHADERPERMUTATION_DIFFUSE;
2122 GL_BlendFunc(GL_ONE, GL_ZERO);
2123 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2126 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2128 if (r_glsl_offsetmapping.integer)
2130 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2131 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2132 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2133 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2134 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2136 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2137 if (r_glsl_offsetmapping_reliefmapping.integer)
2138 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2141 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2142 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2143 // normalmap (deferred prepass), may use alpha test on diffuse
2144 mode = SHADERMODE_DEFERREDGEOMETRY;
2145 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2146 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2147 GL_BlendFunc(GL_ONE, GL_ZERO);
2148 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2150 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2152 if (r_glsl_offsetmapping.integer)
2154 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2155 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2156 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2157 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2158 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2160 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2161 if (r_glsl_offsetmapping_reliefmapping.integer)
2162 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2165 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2166 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2168 mode = SHADERMODE_LIGHTSOURCE;
2169 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2170 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2171 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2172 permutation |= SHADERPERMUTATION_CUBEFILTER;
2173 if (diffusescale > 0)
2174 permutation |= SHADERPERMUTATION_DIFFUSE;
2175 if (specularscale > 0)
2176 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2177 if (r_refdef.fogenabled)
2178 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2179 if (rsurface.texture->colormapping)
2180 permutation |= SHADERPERMUTATION_COLORMAPPING;
2181 if (r_shadow_usingshadowmap2d)
2183 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2184 if(r_shadow_shadowmapvsdct)
2185 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2187 if (r_shadow_shadowmapsampler)
2188 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2189 if (r_shadow_shadowmappcf > 1)
2190 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2191 else if (r_shadow_shadowmappcf)
2192 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2194 if (rsurface.texture->reflectmasktexture)
2195 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2196 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2197 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2199 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2201 if (r_glsl_offsetmapping.integer)
2203 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2204 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2205 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2206 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2207 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2209 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2210 if (r_glsl_offsetmapping_reliefmapping.integer)
2211 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2214 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2215 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2216 // unshaded geometry (fullbright or ambient model lighting)
2217 mode = SHADERMODE_FLATCOLOR;
2218 ambientscale = diffusescale = specularscale = 0;
2219 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2220 permutation |= SHADERPERMUTATION_GLOW;
2221 if (r_refdef.fogenabled)
2222 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2223 if (rsurface.texture->colormapping)
2224 permutation |= SHADERPERMUTATION_COLORMAPPING;
2225 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2227 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2228 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2230 if (r_shadow_shadowmapsampler)
2231 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2232 if (r_shadow_shadowmappcf > 1)
2233 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2234 else if (r_shadow_shadowmappcf)
2235 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2237 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2238 permutation |= SHADERPERMUTATION_REFLECTION;
2239 if (rsurface.texture->reflectmasktexture)
2240 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2241 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2242 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2244 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2246 if (r_glsl_offsetmapping.integer)
2248 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2249 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2250 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2251 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2252 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2254 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2255 if (r_glsl_offsetmapping_reliefmapping.integer)
2256 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2259 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2260 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2261 // directional model lighting
2262 mode = SHADERMODE_LIGHTDIRECTION;
2263 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2264 permutation |= SHADERPERMUTATION_GLOW;
2265 permutation |= SHADERPERMUTATION_DIFFUSE;
2266 if (specularscale > 0)
2267 permutation |= SHADERPERMUTATION_SPECULAR;
2268 if (r_refdef.fogenabled)
2269 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2270 if (rsurface.texture->colormapping)
2271 permutation |= SHADERPERMUTATION_COLORMAPPING;
2272 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2274 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2275 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2277 if (r_shadow_shadowmapsampler)
2278 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2279 if (r_shadow_shadowmappcf > 1)
2280 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2281 else if (r_shadow_shadowmappcf)
2282 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2284 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2285 permutation |= SHADERPERMUTATION_REFLECTION;
2286 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2287 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2288 if (rsurface.texture->reflectmasktexture)
2289 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2290 if (r_shadow_bouncegridtexture)
2292 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2293 if (r_shadow_bouncegriddirectional)
2294 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2296 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2297 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2299 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2301 if (r_glsl_offsetmapping.integer)
2303 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2304 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2305 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2306 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2307 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2309 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2310 if (r_glsl_offsetmapping_reliefmapping.integer)
2311 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2314 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2315 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2316 // ambient model lighting
2317 mode = SHADERMODE_LIGHTDIRECTION;
2318 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2319 permutation |= SHADERPERMUTATION_GLOW;
2320 if (r_refdef.fogenabled)
2321 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2322 if (rsurface.texture->colormapping)
2323 permutation |= SHADERPERMUTATION_COLORMAPPING;
2324 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2326 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2327 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2329 if (r_shadow_shadowmapsampler)
2330 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2331 if (r_shadow_shadowmappcf > 1)
2332 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2333 else if (r_shadow_shadowmappcf)
2334 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2336 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2337 permutation |= SHADERPERMUTATION_REFLECTION;
2338 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2339 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2340 if (rsurface.texture->reflectmasktexture)
2341 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2342 if (r_shadow_bouncegridtexture)
2344 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2345 if (r_shadow_bouncegriddirectional)
2346 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2348 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2349 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2353 if (r_glsl_offsetmapping.integer)
2355 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2356 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2357 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2358 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2359 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2361 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2362 if (r_glsl_offsetmapping_reliefmapping.integer)
2363 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2366 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2367 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2369 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2370 permutation |= SHADERPERMUTATION_GLOW;
2371 if (r_refdef.fogenabled)
2372 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2373 if (rsurface.texture->colormapping)
2374 permutation |= SHADERPERMUTATION_COLORMAPPING;
2375 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2377 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2378 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2380 if (r_shadow_shadowmapsampler)
2381 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2382 if (r_shadow_shadowmappcf > 1)
2383 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2384 else if (r_shadow_shadowmappcf)
2385 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2387 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2388 permutation |= SHADERPERMUTATION_REFLECTION;
2389 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2390 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2391 if (rsurface.texture->reflectmasktexture)
2392 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2393 if (FAKELIGHT_ENABLED)
2395 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2396 mode = SHADERMODE_FAKELIGHT;
2397 permutation |= SHADERPERMUTATION_DIFFUSE;
2398 if (specularscale > 0)
2399 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2401 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2403 // deluxemapping (light direction texture)
2404 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2405 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2407 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2408 permutation |= SHADERPERMUTATION_DIFFUSE;
2409 if (specularscale > 0)
2410 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2412 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2414 // fake deluxemapping (uniform light direction in tangentspace)
2415 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2416 permutation |= SHADERPERMUTATION_DIFFUSE;
2417 if (specularscale > 0)
2418 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2420 else if (rsurface.uselightmaptexture)
2422 // ordinary lightmapping (q1bsp, q3bsp)
2423 mode = SHADERMODE_LIGHTMAP;
2427 // ordinary vertex coloring (q3bsp)
2428 mode = SHADERMODE_VERTEXCOLOR;
2430 if (r_shadow_bouncegridtexture)
2432 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2433 if (r_shadow_bouncegriddirectional)
2434 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2436 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2437 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2439 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2440 colormod = dummy_colormod;
2441 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2442 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2443 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2444 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2445 switch(vid.renderpath)
2447 case RENDERPATH_D3D9:
2449 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2450 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2451 R_SetupShader_SetPermutationHLSL(mode, permutation);
2452 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2453 if (mode == SHADERMODE_LIGHTSOURCE)
2455 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2456 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2460 if (mode == SHADERMODE_LIGHTDIRECTION)
2462 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2465 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2466 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2467 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2468 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2469 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2471 if (mode == SHADERMODE_LIGHTSOURCE)
2473 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2474 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2475 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2476 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2477 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2479 // additive passes are only darkened by fog, not tinted
2480 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2481 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2485 if (mode == SHADERMODE_FLATCOLOR)
2487 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2489 else if (mode == SHADERMODE_LIGHTDIRECTION)
2491 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);
2492 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2493 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2494 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2495 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2496 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2497 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2501 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2502 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2503 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2504 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2505 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2507 // additive passes are only darkened by fog, not tinted
2508 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2509 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2511 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2512 hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2513 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2514 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2515 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2516 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2517 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2518 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2519 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2520 if (mode == SHADERMODE_WATER)
2521 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2523 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2524 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2525 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2526 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2527 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2528 if (rsurface.texture->pantstexture)
2529 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2531 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2532 if (rsurface.texture->shirttexture)
2533 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2535 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2536 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2537 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2538 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2539 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2540 hlslPSSetParameter3f(D3DPSREGISTER_OffsetMapping_ScaleSteps, r_glsl_offsetmapping_scale.value, max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer));
2541 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2542 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2544 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2545 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2546 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2547 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2548 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2549 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2550 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2551 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2552 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2553 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2554 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2555 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2556 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2557 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2558 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2559 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2560 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2561 if (rsurfacepass == RSURFPASS_BACKGROUND)
2563 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2564 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2565 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2569 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2571 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2572 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2573 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2574 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2575 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2577 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2578 if (rsurface.rtlight)
2580 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2581 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2586 case RENDERPATH_D3D10:
2587 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2589 case RENDERPATH_D3D11:
2590 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2592 case RENDERPATH_GL20:
2593 case RENDERPATH_GLES2:
2594 if (!vid.useinterleavedarrays)
2596 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2597 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2598 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2599 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2600 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2601 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2602 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2603 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2607 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2608 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2610 R_SetupShader_SetPermutationGLSL(mode, permutation);
2611 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2612 if (mode == SHADERMODE_LIGHTSOURCE)
2614 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2615 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2616 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2617 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2618 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2619 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2621 // additive passes are only darkened by fog, not tinted
2622 if (r_glsl_permutation->loc_FogColor >= 0)
2623 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2624 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2628 if (mode == SHADERMODE_FLATCOLOR)
2630 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2632 else if (mode == SHADERMODE_LIGHTDIRECTION)
2634 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2635 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2636 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2637 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2638 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2639 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2640 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2644 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2645 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2646 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2647 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2648 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2650 // additive passes are only darkened by fog, not tinted
2651 if (r_glsl_permutation->loc_FogColor >= 0)
2653 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2654 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2656 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2658 if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2659 if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2660 if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2661 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(r_glsl_permutation->loc_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2662 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(r_glsl_permutation->loc_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2663 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2664 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2665 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2666 if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2668 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2669 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2670 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2671 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2672 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2674 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2675 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2676 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2677 if (r_glsl_permutation->loc_Color_Pants >= 0)
2679 if (rsurface.texture->pantstexture)
2680 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2682 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2684 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2686 if (rsurface.texture->shirttexture)
2687 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2689 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2691 if (r_glsl_permutation->loc_FogPlane >= 0) qglUniform4f(r_glsl_permutation->loc_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2692 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2693 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2694 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2695 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform3f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale, max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer));
2696 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2f(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2697 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2698 if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegridmatrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
2699 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2701 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2702 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2703 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2704 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2705 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2706 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2707 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2708 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2709 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2710 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2711 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2712 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2713 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2714 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2715 if (r_glsl_permutation->tex_Texture_ReflectCube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2716 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2717 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2718 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2719 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2720 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2721 if (rsurfacepass == RSURFPASS_BACKGROUND)
2723 if (r_glsl_permutation->tex_Texture_Refraction >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Refraction , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2724 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2725 if (r_glsl_permutation->tex_Texture_Reflection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2729 if (r_glsl_permutation->tex_Texture_Reflection >= 0 && waterplane) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2731 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2732 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2733 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2734 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2735 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2737 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
2738 if (rsurface.rtlight)
2740 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2741 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2744 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2747 case RENDERPATH_GL13:
2748 case RENDERPATH_GL11:
2750 case RENDERPATH_SOFT:
2751 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2752 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2753 R_SetupShader_SetPermutationSoft(mode, permutation);
2754 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2755 if (mode == SHADERMODE_LIGHTSOURCE)
2757 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2758 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2759 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2760 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2761 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2762 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2764 // additive passes are only darkened by fog, not tinted
2765 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2766 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2770 if (mode == SHADERMODE_FLATCOLOR)
2772 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2774 else if (mode == SHADERMODE_LIGHTDIRECTION)
2776 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2777 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2778 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2779 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2780 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2781 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2782 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2786 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2787 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2788 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2789 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2790 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2792 // additive passes are only darkened by fog, not tinted
2793 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2794 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2796 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2797 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2798 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2799 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2800 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2801 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2802 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2803 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2804 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2805 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2807 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2808 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2809 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2810 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2811 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2813 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2814 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2815 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2816 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2818 if (rsurface.texture->pantstexture)
2819 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2821 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2823 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2825 if (rsurface.texture->shirttexture)
2826 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2828 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2830 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2831 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2832 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2833 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2834 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale, max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer));
2835 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2836 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2838 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2839 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2840 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2841 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2842 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2843 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2844 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2845 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2846 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2847 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2848 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2849 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2850 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2851 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2852 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2853 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2854 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2855 if (rsurfacepass == RSURFPASS_BACKGROUND)
2857 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2858 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2859 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2863 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2865 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2866 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2867 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2868 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2869 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2871 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2872 if (rsurface.rtlight)
2874 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2875 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2882 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2884 // select a permutation of the lighting shader appropriate to this
2885 // combination of texture, entity, light source, and fogging, only use the
2886 // minimum features necessary to avoid wasting rendering time in the
2887 // fragment shader on features that are not being used
2888 unsigned int permutation = 0;
2889 unsigned int mode = 0;
2890 const float *lightcolorbase = rtlight->currentcolor;
2891 float ambientscale = rtlight->ambientscale;
2892 float diffusescale = rtlight->diffusescale;
2893 float specularscale = rtlight->specularscale;
2894 // this is the location of the light in view space
2895 vec3_t viewlightorigin;
2896 // this transforms from view space (camera) to light space (cubemap)
2897 matrix4x4_t viewtolight;
2898 matrix4x4_t lighttoview;
2899 float viewtolight16f[16];
2900 float range = 1.0f / r_shadow_deferred_8bitrange.value;
2902 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2903 if (rtlight->currentcubemap != r_texture_whitecube)
2904 permutation |= SHADERPERMUTATION_CUBEFILTER;
2905 if (diffusescale > 0)
2906 permutation |= SHADERPERMUTATION_DIFFUSE;
2907 if (specularscale > 0 && r_shadow_gloss.integer > 0)
2908 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2909 if (r_shadow_usingshadowmap2d)
2911 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2912 if (r_shadow_shadowmapvsdct)
2913 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2915 if (r_shadow_shadowmapsampler)
2916 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2917 if (r_shadow_shadowmappcf > 1)
2918 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2919 else if (r_shadow_shadowmappcf)
2920 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2922 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2923 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2924 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2925 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2926 switch(vid.renderpath)
2928 case RENDERPATH_D3D9:
2930 R_SetupShader_SetPermutationHLSL(mode, permutation);
2931 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2932 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2933 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2934 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2935 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2936 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2937 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2938 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2939 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2940 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2942 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2943 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
2944 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2945 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2946 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
2947 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2950 case RENDERPATH_D3D10:
2951 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2953 case RENDERPATH_D3D11:
2954 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2956 case RENDERPATH_GL20:
2957 case RENDERPATH_GLES2:
2958 R_SetupShader_SetPermutationGLSL(mode, permutation);
2959 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2960 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
2961 if (r_glsl_permutation->loc_DeferredColor_Ambient >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2962 if (r_glsl_permutation->loc_DeferredColor_Diffuse >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2963 if (r_glsl_permutation->loc_DeferredColor_Specular >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2964 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2f( r_glsl_permutation->loc_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2965 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f( r_glsl_permutation->loc_ShadowMap_Parameters , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2966 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f( r_glsl_permutation->loc_SpecularPower , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2967 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2f( r_glsl_permutation->loc_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2968 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
2970 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2971 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2972 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2973 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2974 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
2975 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2977 case RENDERPATH_GL13:
2978 case RENDERPATH_GL11:
2980 case RENDERPATH_SOFT:
2981 R_SetupShader_SetPermutationGLSL(mode, permutation);
2982 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2983 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
2984 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2985 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2986 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2987 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2988 DPSOFTRAST_Uniform4f( DPSOFTRAST_UNIFORM_ShadowMap_Parameters , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2989 DPSOFTRAST_Uniform1f( DPSOFTRAST_UNIFORM_SpecularPower , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2990 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2991 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2993 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2994 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2995 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2996 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2997 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
2998 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3003 #define SKINFRAME_HASH 1024
3007 int loadsequence; // incremented each level change
3008 memexpandablearray_t array;
3009 skinframe_t *hash[SKINFRAME_HASH];
3012 r_skinframe_t r_skinframe;
3014 void R_SkinFrame_PrepareForPurge(void)
3016 r_skinframe.loadsequence++;
3017 // wrap it without hitting zero
3018 if (r_skinframe.loadsequence >= 200)
3019 r_skinframe.loadsequence = 1;
3022 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3026 // mark the skinframe as used for the purging code
3027 skinframe->loadsequence = r_skinframe.loadsequence;
3030 void R_SkinFrame_Purge(void)
3034 for (i = 0;i < SKINFRAME_HASH;i++)
3036 for (s = r_skinframe.hash[i];s;s = s->next)
3038 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3040 if (s->merged == s->base)
3042 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3043 R_PurgeTexture(s->stain );s->stain = NULL;
3044 R_PurgeTexture(s->merged);s->merged = NULL;
3045 R_PurgeTexture(s->base );s->base = NULL;
3046 R_PurgeTexture(s->pants );s->pants = NULL;
3047 R_PurgeTexture(s->shirt );s->shirt = NULL;
3048 R_PurgeTexture(s->nmap );s->nmap = NULL;
3049 R_PurgeTexture(s->gloss );s->gloss = NULL;
3050 R_PurgeTexture(s->glow );s->glow = NULL;
3051 R_PurgeTexture(s->fog );s->fog = NULL;
3052 R_PurgeTexture(s->reflect);s->reflect = NULL;
3053 s->loadsequence = 0;
3059 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3061 char basename[MAX_QPATH];
3063 Image_StripImageExtension(name, basename, sizeof(basename));
3065 if( last == NULL ) {
3067 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3068 item = r_skinframe.hash[hashindex];
3073 // linearly search through the hash bucket
3074 for( ; item ; item = item->next ) {
3075 if( !strcmp( item->basename, basename ) ) {
3082 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3086 char basename[MAX_QPATH];
3088 Image_StripImageExtension(name, basename, sizeof(basename));
3090 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3091 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3092 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3096 rtexture_t *dyntexture;
3097 // check whether its a dynamic texture
3098 dyntexture = CL_GetDynTexture( basename );
3099 if (!add && !dyntexture)
3101 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3102 memset(item, 0, sizeof(*item));
3103 strlcpy(item->basename, basename, sizeof(item->basename));
3104 item->base = dyntexture; // either NULL or dyntexture handle
3105 item->textureflags = textureflags;
3106 item->comparewidth = comparewidth;
3107 item->compareheight = compareheight;
3108 item->comparecrc = comparecrc;
3109 item->next = r_skinframe.hash[hashindex];
3110 r_skinframe.hash[hashindex] = item;
3112 else if( item->base == NULL )
3114 rtexture_t *dyntexture;
3115 // check whether its a dynamic texture
3116 // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black]
3117 dyntexture = CL_GetDynTexture( basename );
3118 item->base = dyntexture; // either NULL or dyntexture handle
3121 R_SkinFrame_MarkUsed(item);
3125 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3127 unsigned long long avgcolor[5], wsum; \
3135 for(pix = 0; pix < cnt; ++pix) \
3138 for(comp = 0; comp < 3; ++comp) \
3140 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3143 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3145 for(comp = 0; comp < 3; ++comp) \
3146 avgcolor[comp] += getpixel * w; \
3149 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3150 avgcolor[4] += getpixel; \
3152 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3154 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3155 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3156 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3157 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3160 extern cvar_t gl_picmip;
3161 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3164 unsigned char *pixels;
3165 unsigned char *bumppixels;
3166 unsigned char *basepixels = NULL;
3167 int basepixels_width = 0;
3168 int basepixels_height = 0;
3169 skinframe_t *skinframe;
3170 rtexture_t *ddsbase = NULL;
3171 qboolean ddshasalpha = false;
3172 float ddsavgcolor[4];
3173 char basename[MAX_QPATH];
3174 int miplevel = R_PicmipForFlags(textureflags);
3175 int savemiplevel = miplevel;
3178 if (cls.state == ca_dedicated)
3181 // return an existing skinframe if already loaded
3182 // if loading of the first image fails, don't make a new skinframe as it
3183 // would cause all future lookups of this to be missing
3184 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3185 if (skinframe && skinframe->base)
3188 Image_StripImageExtension(name, basename, sizeof(basename));
3190 // check for DDS texture file first
3191 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3193 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
3194 if (basepixels == NULL)
3198 // FIXME handle miplevel
3200 if (developer_loading.integer)
3201 Con_Printf("loading skin \"%s\"\n", name);
3203 // we've got some pixels to store, so really allocate this new texture now
3205 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3206 skinframe->stain = NULL;
3207 skinframe->merged = NULL;
3208 skinframe->base = NULL;
3209 skinframe->pants = NULL;
3210 skinframe->shirt = NULL;
3211 skinframe->nmap = NULL;
3212 skinframe->gloss = NULL;
3213 skinframe->glow = NULL;
3214 skinframe->fog = NULL;
3215 skinframe->reflect = NULL;
3216 skinframe->hasalpha = false;
3220 skinframe->base = ddsbase;
3221 skinframe->hasalpha = ddshasalpha;
3222 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3223 if (r_loadfog && skinframe->hasalpha)
3224 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3225 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3229 basepixels_width = image_width;
3230 basepixels_height = image_height;
3231 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3232 if (textureflags & TEXF_ALPHA)
3234 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3236 if (basepixels[j] < 255)
3238 skinframe->hasalpha = true;
3242 if (r_loadfog && skinframe->hasalpha)
3244 // has transparent pixels
3245 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3246 for (j = 0;j < image_width * image_height * 4;j += 4)
3251 pixels[j+3] = basepixels[j+3];
3253 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3257 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3258 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3259 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3260 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
3261 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3262 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
3267 mymiplevel = savemiplevel;
3268 if (r_loadnormalmap)
3269 skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel);
3270 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3272 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3273 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3274 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3275 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3278 // _norm is the name used by tenebrae and has been adopted as standard
3279 if (r_loadnormalmap && skinframe->nmap == NULL)
3281 mymiplevel = savemiplevel;
3282 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3284 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3288 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3290 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3291 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3292 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3294 Mem_Free(bumppixels);
3296 else if (r_shadow_bumpscale_basetexture.value > 0)
3298 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3299 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3300 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3303 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3304 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
3307 // _luma is supported only for tenebrae compatibility
3308 // _glow is the preferred name
3309 mymiplevel = savemiplevel;
3310 if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel))))
3312 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3313 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3314 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
3315 Mem_Free(pixels);pixels = NULL;
3318 mymiplevel = savemiplevel;
3319 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3321 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3322 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3323 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
3328 mymiplevel = savemiplevel;
3329 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3331 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3332 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3333 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
3338 mymiplevel = savemiplevel;
3339 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3341 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3342 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3343 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
3348 mymiplevel = savemiplevel;
3349 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3351 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3352 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3353 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
3359 Mem_Free(basepixels);
3364 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3365 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
3368 unsigned char *temp1, *temp2;
3369 skinframe_t *skinframe;
3371 if (cls.state == ca_dedicated)
3374 // if already loaded just return it, otherwise make a new skinframe
3375 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3376 if (skinframe && skinframe->base)
3379 skinframe->stain = NULL;
3380 skinframe->merged = NULL;
3381 skinframe->base = NULL;
3382 skinframe->pants = NULL;
3383 skinframe->shirt = NULL;
3384 skinframe->nmap = NULL;
3385 skinframe->gloss = NULL;
3386 skinframe->glow = NULL;
3387 skinframe->fog = NULL;
3388 skinframe->reflect = NULL;
3389 skinframe->hasalpha = false;
3391 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3395 if (developer_loading.integer)
3396 Con_Printf("loading 32bit skin \"%s\"\n", name);
3398 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3400 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3401 temp2 = temp1 + width * height * 4;
3402 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3403 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3406 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
3407 if (textureflags & TEXF_ALPHA)
3409 for (i = 3;i < width * height * 4;i += 4)
3411 if (skindata[i] < 255)
3413 skinframe->hasalpha = true;
3417 if (r_loadfog && skinframe->hasalpha)
3419 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3420 memcpy(fogpixels, skindata, width * height * 4);
3421 for (i = 0;i < width * height * 4;i += 4)
3422 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3423 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3424 Mem_Free(fogpixels);
3428 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3429 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3434 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3438 skinframe_t *skinframe;
3440 if (cls.state == ca_dedicated)
3443 // if already loaded just return it, otherwise make a new skinframe
3444 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3445 if (skinframe && skinframe->base)
3448 skinframe->stain = NULL;
3449 skinframe->merged = NULL;
3450 skinframe->base = NULL;
3451 skinframe->pants = NULL;
3452 skinframe->shirt = NULL;
3453 skinframe->nmap = NULL;
3454 skinframe->gloss = NULL;
3455 skinframe->glow = NULL;
3456 skinframe->fog = NULL;
3457 skinframe->reflect = NULL;
3458 skinframe->hasalpha = false;
3460 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3464 if (developer_loading.integer)
3465 Con_Printf("loading quake skin \"%s\"\n", name);
3467 // we actually don't upload anything until the first use, because mdl skins frequently go unused, and are almost never used in both modes (colormapped and non-colormapped)
3468 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3469 memcpy(skinframe->qpixels, skindata, width*height);
3470 skinframe->qwidth = width;
3471 skinframe->qheight = height;
3474 for (i = 0;i < width * height;i++)
3475 featuresmask |= palette_featureflags[skindata[i]];
3477 skinframe->hasalpha = false;
3478 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3479 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3480 skinframe->qgeneratemerged = true;
3481 skinframe->qgeneratebase = skinframe->qhascolormapping;
3482 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3484 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3485 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3490 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3494 unsigned char *skindata;
3496 if (!skinframe->qpixels)
3499 if (!skinframe->qhascolormapping)
3500 colormapped = false;
3504 if (!skinframe->qgeneratebase)
3509 if (!skinframe->qgeneratemerged)
3513 width = skinframe->qwidth;
3514 height = skinframe->qheight;
3515 skindata = skinframe->qpixels;
3517 if (skinframe->qgeneratenmap)
3519 unsigned char *temp1, *temp2;
3520 skinframe->qgeneratenmap = false;
3521 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3522 temp2 = temp1 + width * height * 4;
3523 // use either a custom palette or the quake palette
3524 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3525 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3526 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3530 if (skinframe->qgenerateglow)
3532 skinframe->qgenerateglow = false;
3533 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3538 skinframe->qgeneratebase = false;
3539 skinframe->base = R_LoadTexture2D(r_main_texturepool, va("%s_nospecial", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
3540 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3541 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3545 skinframe->qgeneratemerged = false;
3546 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
3549 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3551 Mem_Free(skinframe->qpixels);
3552 skinframe->qpixels = NULL;
3556 skinframe_t *R_SkinFrame_LoadInternal8bit(const char *name, int textureflags, const unsigned char *skindata, int width, int height, const unsigned int *palette, const unsigned int *alphapalette)
3559 skinframe_t *skinframe;
3561 if (cls.state == ca_dedicated)
3564 // if already loaded just return it, otherwise make a new skinframe
3565 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3566 if (skinframe && skinframe->base)
3569 skinframe->stain = NULL;
3570 skinframe->merged = NULL;
3571 skinframe->base = NULL;
3572 skinframe->pants = NULL;
3573 skinframe->shirt = NULL;
3574 skinframe->nmap = NULL;
3575 skinframe->gloss = NULL;
3576 skinframe->glow = NULL;
3577 skinframe->fog = NULL;
3578 skinframe->reflect = NULL;
3579 skinframe->hasalpha = false;
3581 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3585 if (developer_loading.integer)
3586 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3588 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3589 if (textureflags & TEXF_ALPHA)
3591 for (i = 0;i < width * height;i++)
3593 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3595 skinframe->hasalpha = true;
3599 if (r_loadfog && skinframe->hasalpha)
3600 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3603 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3604 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3609 skinframe_t *R_SkinFrame_LoadMissing(void)
3611 skinframe_t *skinframe;
3613 if (cls.state == ca_dedicated)
3616 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3617 skinframe->stain = NULL;
3618 skinframe->merged = NULL;
3619 skinframe->base = NULL;
3620 skinframe->pants = NULL;
3621 skinframe->shirt = NULL;
3622 skinframe->nmap = NULL;
3623 skinframe->gloss = NULL;
3624 skinframe->glow = NULL;
3625 skinframe->fog = NULL;
3626 skinframe->reflect = NULL;
3627 skinframe->hasalpha = false;
3629 skinframe->avgcolor[0] = rand() / RAND_MAX;
3630 skinframe->avgcolor[1] = rand() / RAND_MAX;
3631 skinframe->avgcolor[2] = rand() / RAND_MAX;
3632 skinframe->avgcolor[3] = 1;
3637 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3638 typedef struct suffixinfo_s
3641 qboolean flipx, flipy, flipdiagonal;
3644 static suffixinfo_t suffix[3][6] =
3647 {"px", false, false, false},
3648 {"nx", false, false, false},
3649 {"py", false, false, false},
3650 {"ny", false, false, false},
3651 {"pz", false, false, false},
3652 {"nz", false, false, false}
3655 {"posx", false, false, false},
3656 {"negx", false, false, false},
3657 {"posy", false, false, false},
3658 {"negy", false, false, false},
3659 {"posz", false, false, false},
3660 {"negz", false, false, false}
3663 {"rt", true, false, true},
3664 {"lf", false, true, true},
3665 {"ft", true, true, false},
3666 {"bk", false, false, false},
3667 {"up", true, false, true},
3668 {"dn", true, false, true}
3672 static int componentorder[4] = {0, 1, 2, 3};
3674 rtexture_t *R_LoadCubemap(const char *basename)
3676 int i, j, cubemapsize;
3677 unsigned char *cubemappixels, *image_buffer;
3678 rtexture_t *cubemaptexture;
3680 // must start 0 so the first loadimagepixels has no requested width/height
3682 cubemappixels = NULL;
3683 cubemaptexture = NULL;
3684 // keep trying different suffix groups (posx, px, rt) until one loads
3685 for (j = 0;j < 3 && !cubemappixels;j++)
3687 // load the 6 images in the suffix group
3688 for (i = 0;i < 6;i++)
3690 // generate an image name based on the base and and suffix
3691 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3693 if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
3695 // an image loaded, make sure width and height are equal
3696 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3698 // if this is the first image to load successfully, allocate the cubemap memory
3699 if (!cubemappixels && image_width >= 1)
3701 cubemapsize = image_width;
3702 // note this clears to black, so unavailable sides are black
3703 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3705 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3707 Image_CopyMux(cubemappixels+i*cubemapsize*cubemapsize*4, image_buffer, cubemapsize, cubemapsize, suffix[j][i].flipx, suffix[j][i].flipy, suffix[j][i].flipdiagonal, 4, 4, componentorder);
3710 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3712 Mem_Free(image_buffer);
3716 // if a cubemap loaded, upload it
3719 if (developer_loading.integer)
3720 Con_Printf("loading cubemap \"%s\"\n", basename);
3722 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3723 Mem_Free(cubemappixels);
3727 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3728 if (developer_loading.integer)
3730 Con_Printf("(tried tried images ");
3731 for (j = 0;j < 3;j++)
3732 for (i = 0;i < 6;i++)
3733 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3734 Con_Print(" and was unable to find any of them).\n");
3737 return cubemaptexture;
3740 rtexture_t *R_GetCubemap(const char *basename)
3743 for (i = 0;i < r_texture_numcubemaps;i++)
3744 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3745 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3746 if (i >= MAX_CUBEMAPS)
3747 return r_texture_whitecube;
3748 r_texture_numcubemaps++;
3749 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3750 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3751 return r_texture_cubemaps[i].texture;
3754 void R_FreeCubemaps(void)
3757 for (i = 0;i < r_texture_numcubemaps;i++)
3759 if (developer_loading.integer)
3760 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3761 if (r_texture_cubemaps[i].texture)
3762 R_FreeTexture(r_texture_cubemaps[i].texture);
3764 r_texture_numcubemaps = 0;
3767 void R_Main_FreeViewCache(void)
3769 if (r_refdef.viewcache.entityvisible)
3770 Mem_Free(r_refdef.viewcache.entityvisible);
3771 if (r_refdef.viewcache.world_pvsbits)
3772 Mem_Free(r_refdef.viewcache.world_pvsbits);
3773 if (r_refdef.viewcache.world_leafvisible)
3774 Mem_Free(r_refdef.viewcache.world_leafvisible);
3775 if (r_refdef.viewcache.world_surfacevisible)
3776 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3777 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3780 void R_Main_ResizeViewCache(void)
3782 int numentities = r_refdef.scene.numentities;
3783 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3784 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3785 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3786 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3787 if (r_refdef.viewcache.maxentities < numentities)
3789 r_refdef.viewcache.maxentities = numentities;
3790 if (r_refdef.viewcache.entityvisible)
3791 Mem_Free(r_refdef.viewcache.entityvisible);
3792 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3794 if (r_refdef.viewcache.world_numclusters != numclusters)
3796 r_refdef.viewcache.world_numclusters = numclusters;
3797 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3798 if (r_refdef.viewcache.world_pvsbits)
3799 Mem_Free(r_refdef.viewcache.world_pvsbits);
3800 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3802 if (r_refdef.viewcache.world_numleafs != numleafs)
3804 r_refdef.viewcache.world_numleafs = numleafs;
3805 if (r_refdef.viewcache.world_leafvisible)
3806 Mem_Free(r_refdef.viewcache.world_leafvisible);
3807 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3809 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3811 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3812 if (r_refdef.viewcache.world_surfacevisible)
3813 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3814 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3818 extern rtexture_t *loadingscreentexture;
3819 void gl_main_start(void)
3821 loadingscreentexture = NULL;
3822 r_texture_blanknormalmap = NULL;
3823 r_texture_white = NULL;
3824 r_texture_grey128 = NULL;
3825 r_texture_black = NULL;
3826 r_texture_whitecube = NULL;
3827 r_texture_normalizationcube = NULL;
3828 r_texture_fogattenuation = NULL;
3829 r_texture_fogheighttexture = NULL;
3830 r_texture_gammaramps = NULL;
3831 r_texture_numcubemaps = 0;
3833 r_loaddds = r_texture_dds_load.integer != 0;
3834 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3836 switch(vid.renderpath)
3838 case RENDERPATH_GL20:
3839 case RENDERPATH_D3D9:
3840 case RENDERPATH_D3D10:
3841 case RENDERPATH_D3D11:
3842 case RENDERPATH_SOFT:
3843 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3844 Cvar_SetValueQuick(&gl_combine, 1);
3845 Cvar_SetValueQuick(&r_glsl, 1);
3846 r_loadnormalmap = true;
3850 case RENDERPATH_GL13:
3851 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3852 Cvar_SetValueQuick(&gl_combine, 1);
3853 Cvar_SetValueQuick(&r_glsl, 0);
3854 r_loadnormalmap = false;
3855 r_loadgloss = false;
3858 case RENDERPATH_GL11:
3859 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3860 Cvar_SetValueQuick(&gl_combine, 0);
3861 Cvar_SetValueQuick(&r_glsl, 0);
3862 r_loadnormalmap = false;
3863 r_loadgloss = false;
3866 case RENDERPATH_GLES2:
3867 Cvar_SetValueQuick(&r_textureunits, 1);
3868 Cvar_SetValueQuick(&gl_combine, 1);
3869 Cvar_SetValueQuick(&r_glsl, 1);
3870 r_loadnormalmap = true;
3871 r_loadgloss = false;
3877 R_FrameData_Reset();
3881 memset(r_queries, 0, sizeof(r_queries));
3883 r_qwskincache = NULL;
3884 r_qwskincache_size = 0;
3886 // due to caching of texture_t references, the collision cache must be reset
3887 Collision_Cache_Reset(true);
3889 // set up r_skinframe loading system for textures
3890 memset(&r_skinframe, 0, sizeof(r_skinframe));
3891 r_skinframe.loadsequence = 1;
3892 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3894 r_main_texturepool = R_AllocTexturePool();
3895 R_BuildBlankTextures();
3897 if (vid.support.arb_texture_cube_map)
3900 R_BuildNormalizationCube();
3902 r_texture_fogattenuation = NULL;
3903 r_texture_fogheighttexture = NULL;
3904 r_texture_gammaramps = NULL;
3905 //r_texture_fogintensity = NULL;
3906 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3907 memset(&r_waterstate, 0, sizeof(r_waterstate));
3908 r_glsl_permutation = NULL;
3909 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3910 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3911 glslshaderstring = NULL;
3913 r_hlsl_permutation = NULL;
3914 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3915 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3917 hlslshaderstring = NULL;
3918 memset(&r_svbsp, 0, sizeof (r_svbsp));
3920 r_refdef.fogmasktable_density = 0;
3923 void gl_main_shutdown(void)
3926 R_FrameData_Reset();
3928 R_Main_FreeViewCache();
3930 switch(vid.renderpath)
3932 case RENDERPATH_GL11:
3933 case RENDERPATH_GL13:
3934 case RENDERPATH_GL20:
3935 case RENDERPATH_GLES2:
3937 qglDeleteQueriesARB(r_maxqueries, r_queries);
3939 case RENDERPATH_D3D9:
3940 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3942 case RENDERPATH_D3D10:
3943 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3945 case RENDERPATH_D3D11:
3946 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3948 case RENDERPATH_SOFT:
3954 memset(r_queries, 0, sizeof(r_queries));
3956 r_qwskincache = NULL;
3957 r_qwskincache_size = 0;
3959 // clear out the r_skinframe state
3960 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3961 memset(&r_skinframe, 0, sizeof(r_skinframe));
3964 Mem_Free(r_svbsp.nodes);
3965 memset(&r_svbsp, 0, sizeof (r_svbsp));
3966 R_FreeTexturePool(&r_main_texturepool);
3967 loadingscreentexture = NULL;
3968 r_texture_blanknormalmap = NULL;
3969 r_texture_white = NULL;
3970 r_texture_grey128 = NULL;
3971 r_texture_black = NULL;
3972 r_texture_whitecube = NULL;
3973 r_texture_normalizationcube = NULL;
3974 r_texture_fogattenuation = NULL;
3975 r_texture_fogheighttexture = NULL;
3976 r_texture_gammaramps = NULL;
3977 r_texture_numcubemaps = 0;
3978 //r_texture_fogintensity = NULL;
3979 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3980 memset(&r_waterstate, 0, sizeof(r_waterstate));
3983 r_glsl_permutation = NULL;
3984 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3985 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3986 glslshaderstring = NULL;
3988 r_hlsl_permutation = NULL;
3989 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3990 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3992 hlslshaderstring = NULL;
3995 extern void CL_ParseEntityLump(char *entitystring);
3996 void gl_main_newmap(void)
3998 // FIXME: move this code to client
3999 char *entities, entname[MAX_QPATH];
4001 Mem_Free(r_qwskincache);
4002 r_qwskincache = NULL;
4003 r_qwskincache_size = 0;
4006 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4007 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4009 CL_ParseEntityLump(entities);
4013 if (cl.worldmodel->brush.entities)
4014 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4016 R_Main_FreeViewCache();
4018 R_FrameData_Reset();
4021 void GL_Main_Init(void)
4023 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4025 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4026 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4027 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4028 if (gamemode == GAME_NEHAHRA)
4030 Cvar_RegisterVariable (&gl_fogenable);
4031 Cvar_RegisterVariable (&gl_fogdensity);
4032 Cvar_RegisterVariable (&gl_fogred);
4033 Cvar_RegisterVariable (&gl_foggreen);
4034 Cvar_RegisterVariable (&gl_fogblue);
4035 Cvar_RegisterVariable (&gl_fogstart);
4036 Cvar_RegisterVariable (&gl_fogend);
4037 Cvar_RegisterVariable (&gl_skyclip);
4039 Cvar_RegisterVariable(&r_motionblur);
4040 Cvar_RegisterVariable(&r_motionblur_maxblur);
4041 Cvar_RegisterVariable(&r_motionblur_bmin);
4042 Cvar_RegisterVariable(&r_motionblur_vmin);
4043 Cvar_RegisterVariable(&r_motionblur_vmax);
4044 Cvar_RegisterVariable(&r_motionblur_vcoeff);
4045 Cvar_RegisterVariable(&r_motionblur_randomize);
4046 Cvar_RegisterVariable(&r_damageblur);
4047 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4048 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4049 Cvar_RegisterVariable(&r_equalize_entities_by);
4050 Cvar_RegisterVariable(&r_equalize_entities_to);
4051 Cvar_RegisterVariable(&r_depthfirst);
4052 Cvar_RegisterVariable(&r_useinfinitefarclip);
4053 Cvar_RegisterVariable(&r_farclip_base);
4054 Cvar_RegisterVariable(&r_farclip_world);
4055 Cvar_RegisterVariable(&r_nearclip);
4056 Cvar_RegisterVariable(&r_showbboxes);
4057 Cvar_RegisterVariable(&r_showsurfaces);
4058 Cvar_RegisterVariable(&r_showtris);
4059 Cvar_RegisterVariable(&r_shownormals);
4060 Cvar_RegisterVariable(&r_showlighting);
4061 Cvar_RegisterVariable(&r_showshadowvolumes);
4062 Cvar_RegisterVariable(&r_showcollisionbrushes);
4063 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4064 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4065 Cvar_RegisterVariable(&r_showdisabledepthtest);
4066 Cvar_RegisterVariable(&r_drawportals);
4067 Cvar_RegisterVariable(&r_drawentities);
4068 Cvar_RegisterVariable(&r_draw2d);
4069 Cvar_RegisterVariable(&r_drawworld);
4070 Cvar_RegisterVariable(&r_cullentities_trace);
4071 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4072 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4073 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4074 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4075 Cvar_RegisterVariable(&r_drawviewmodel);
4076 Cvar_RegisterVariable(&r_drawexteriormodel);
4077 Cvar_RegisterVariable(&r_speeds);
4078 Cvar_RegisterVariable(&r_fullbrights);
4079 Cvar_RegisterVariable(&r_wateralpha);
4080 Cvar_RegisterVariable(&r_dynamic);
4081 Cvar_RegisterVariable(&r_fakelight);
4082 Cvar_RegisterVariable(&r_fakelight_intensity);
4083 Cvar_RegisterVariable(&r_fullbright);
4084 Cvar_RegisterVariable(&r_shadows);
4085 Cvar_RegisterVariable(&r_shadows_darken);
4086 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4087 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4088 Cvar_RegisterVariable(&r_shadows_throwdistance);
4089 Cvar_RegisterVariable(&r_shadows_throwdirection);
4090 Cvar_RegisterVariable(&r_shadows_focus);
4091 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4092 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4093 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4094 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4095 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4096 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4097 Cvar_RegisterVariable(&r_fog_exp2);
4098 Cvar_RegisterVariable(&r_fog_clear);
4099 Cvar_RegisterVariable(&r_drawfog);
4100 Cvar_RegisterVariable(&r_transparentdepthmasking);
4101 Cvar_RegisterVariable(&r_texture_dds_load);
4102 Cvar_RegisterVariable(&r_texture_dds_save);
4103 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
4104 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
4105 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
4106 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
4107 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
4108 Cvar_RegisterVariable(&r_textureunits);
4109 Cvar_RegisterVariable(&gl_combine);
4110 Cvar_RegisterVariable(&r_viewfbo);
4111 Cvar_RegisterVariable(&r_viewscale);
4112 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4113 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4114 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4115 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4116 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4117 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4118 Cvar_RegisterVariable(&r_glsl);
4119 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4120 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4121 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4122 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4123 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4124 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4125 Cvar_RegisterVariable(&r_glsl_postprocess);
4126 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4127 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4128 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4129 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4130 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4131 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4132 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4133 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4135 Cvar_RegisterVariable(&r_water);
4136 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4137 Cvar_RegisterVariable(&r_water_clippingplanebias);
4138 Cvar_RegisterVariable(&r_water_refractdistort);
4139 Cvar_RegisterVariable(&r_water_reflectdistort);
4140 Cvar_RegisterVariable(&r_water_scissormode);
4141 Cvar_RegisterVariable(&r_lerpsprites);
4142 Cvar_RegisterVariable(&r_lerpmodels);
4143 Cvar_RegisterVariable(&r_lerplightstyles);
4144 Cvar_RegisterVariable(&r_waterscroll);
4145 Cvar_RegisterVariable(&r_bloom);
4146 Cvar_RegisterVariable(&r_bloom_colorscale);
4147 Cvar_RegisterVariable(&r_bloom_brighten);
4148 Cvar_RegisterVariable(&r_bloom_blur);
4149 Cvar_RegisterVariable(&r_bloom_resolution);
4150 Cvar_RegisterVariable(&r_bloom_colorexponent);
4151 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4152 Cvar_RegisterVariable(&r_hdr);
4153 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4154 Cvar_RegisterVariable(&r_hdr_glowintensity);
4155 Cvar_RegisterVariable(&r_hdr_range);
4156 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4157 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4158 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4159 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4160 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4161 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4162 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4163 Cvar_RegisterVariable(&developer_texturelogging);
4164 Cvar_RegisterVariable(&gl_lightmaps);
4165 Cvar_RegisterVariable(&r_test);
4166 Cvar_RegisterVariable(&r_glsl_saturation);
4167 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4168 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4169 Cvar_RegisterVariable(&r_framedatasize);
4170 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4171 Cvar_SetValue("r_fullbrights", 0);
4172 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4174 Cvar_RegisterVariable(&r_track_sprites);
4175 Cvar_RegisterVariable(&r_track_sprites_flags);
4176 Cvar_RegisterVariable(&r_track_sprites_scalew);
4177 Cvar_RegisterVariable(&r_track_sprites_scaleh);
4178 Cvar_RegisterVariable(&r_overheadsprites_perspective);
4179 Cvar_RegisterVariable(&r_overheadsprites_pushback);
4180 Cvar_RegisterVariable(&r_overheadsprites_scalex);
4181 Cvar_RegisterVariable(&r_overheadsprites_scaley);
4184 extern void R_Textures_Init(void);
4185 extern void GL_Draw_Init(void);
4186 extern void GL_Main_Init(void);
4187 extern void R_Shadow_Init(void);
4188 extern void R_Sky_Init(void);
4189 extern void GL_Surf_Init(void);
4190 extern void R_Particles_Init(void);
4191 extern void R_Explosion_Init(void);
4192 extern void gl_backend_init(void);
4193 extern void Sbar_Init(void);
4194 extern void R_LightningBeams_Init(void);
4195 extern void Mod_RenderInit(void);
4196 extern void Font_Init(void);
4198 void Render_Init(void)
4211 R_LightningBeams_Init();
4220 extern char *ENGINE_EXTENSIONS;
4223 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4224 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4225 gl_version = (const char *)qglGetString(GL_VERSION);
4226 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4230 if (!gl_platformextensions)
4231 gl_platformextensions = "";
4233 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4234 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4235 Con_Printf("GL_VERSION: %s\n", gl_version);
4236 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4237 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4239 VID_CheckExtensions();
4241 // LordHavoc: report supported extensions
4242 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4244 // clear to black (loading plaque will be seen over this)
4245 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4248 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4252 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4254 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4257 p = r_refdef.view.frustum + i;
4262 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4266 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4270 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4274 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4278 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4282 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4286 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4290 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4298 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4302 for (i = 0;i < numplanes;i++)
4309 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4313 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4317 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4321 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4325 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4329 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4333 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4337 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4345 //==================================================================================
4347 // LordHavoc: this stores temporary data used within the same frame
4349 typedef struct r_framedata_mem_s
4351 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4352 size_t size; // how much usable space
4353 size_t current; // how much space in use
4354 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4355 size_t wantedsize; // how much space was allocated
4356 unsigned char *data; // start of real data (16byte aligned)
4360 static r_framedata_mem_t *r_framedata_mem;
4362 void R_FrameData_Reset(void)
4364 while (r_framedata_mem)
4366 r_framedata_mem_t *next = r_framedata_mem->purge;
4367 Mem_Free(r_framedata_mem);
4368 r_framedata_mem = next;
4372 void R_FrameData_Resize(void)
4375 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4376 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4377 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4379 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4380 newmem->wantedsize = wantedsize;
4381 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4382 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4383 newmem->current = 0;
4385 newmem->purge = r_framedata_mem;
4386 r_framedata_mem = newmem;
4390 void R_FrameData_NewFrame(void)
4392 R_FrameData_Resize();
4393 if (!r_framedata_mem)
4395 // if we ran out of space on the last frame, free the old memory now
4396 while (r_framedata_mem->purge)
4398 // repeatedly remove the second item in the list, leaving only head
4399 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4400 Mem_Free(r_framedata_mem->purge);
4401 r_framedata_mem->purge = next;
4403 // reset the current mem pointer
4404 r_framedata_mem->current = 0;
4405 r_framedata_mem->mark = 0;
4408 void *R_FrameData_Alloc(size_t size)
4412 // align to 16 byte boundary - the data pointer is already aligned, so we
4413 // only need to ensure the size of every allocation is also aligned
4414 size = (size + 15) & ~15;
4416 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4418 // emergency - we ran out of space, allocate more memory
4419 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4420 R_FrameData_Resize();
4423 data = r_framedata_mem->data + r_framedata_mem->current;
4424 r_framedata_mem->current += size;
4426 // count the usage for stats
4427 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4428 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4430 return (void *)data;
4433 void *R_FrameData_Store(size_t size, void *data)
4435 void *d = R_FrameData_Alloc(size);
4437 memcpy(d, data, size);
4441 void R_FrameData_SetMark(void)
4443 if (!r_framedata_mem)
4445 r_framedata_mem->mark = r_framedata_mem->current;
4448 void R_FrameData_ReturnToMark(void)
4450 if (!r_framedata_mem)
4452 r_framedata_mem->current = r_framedata_mem->mark;
4455 //==================================================================================
4457 // LordHavoc: animcache originally written by Echon, rewritten since then
4460 * Animation cache prevents re-generating mesh data for an animated model
4461 * multiple times in one frame for lighting, shadowing, reflections, etc.
4464 void R_AnimCache_Free(void)
4468 void R_AnimCache_ClearCache(void)
4471 entity_render_t *ent;
4473 for (i = 0;i < r_refdef.scene.numentities;i++)
4475 ent = r_refdef.scene.entities[i];
4476 ent->animcache_vertex3f = NULL;
4477 ent->animcache_normal3f = NULL;
4478 ent->animcache_svector3f = NULL;
4479 ent->animcache_tvector3f = NULL;
4480 ent->animcache_vertexmesh = NULL;
4481 ent->animcache_vertex3fbuffer = NULL;
4482 ent->animcache_vertexmeshbuffer = NULL;
4486 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4490 // check if we need the meshbuffers
4491 if (!vid.useinterleavedarrays)
4494 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4495 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4496 // TODO: upload vertex3f buffer?
4497 if (ent->animcache_vertexmesh)
4499 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4500 for (i = 0;i < numvertices;i++)
4501 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4502 if (ent->animcache_svector3f)
4503 for (i = 0;i < numvertices;i++)
4504 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4505 if (ent->animcache_tvector3f)
4506 for (i = 0;i < numvertices;i++)
4507 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4508 if (ent->animcache_normal3f)
4509 for (i = 0;i < numvertices;i++)
4510 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4511 // TODO: upload vertexmeshbuffer?
4515 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4517 dp_model_t *model = ent->model;
4519 // see if it's already cached this frame
4520 if (ent->animcache_vertex3f)
4522 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4523 if (wantnormals || wanttangents)
4525 if (ent->animcache_normal3f)
4526 wantnormals = false;
4527 if (ent->animcache_svector3f)
4528 wanttangents = false;
4529 if (wantnormals || wanttangents)
4531 numvertices = model->surfmesh.num_vertices;
4533 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4536 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4537 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4539 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4540 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4546 // see if this ent is worth caching
4547 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4549 // get some memory for this entity and generate mesh data
4550 numvertices = model->surfmesh.num_vertices;
4551 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4553 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4556 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4557 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4559 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4560 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4565 void R_AnimCache_CacheVisibleEntities(void)
4568 qboolean wantnormals = true;
4569 qboolean wanttangents = !r_showsurfaces.integer;
4571 switch(vid.renderpath)
4573 case RENDERPATH_GL20:
4574 case RENDERPATH_D3D9:
4575 case RENDERPATH_D3D10:
4576 case RENDERPATH_D3D11:
4577 case RENDERPATH_GLES2:
4579 case RENDERPATH_GL13:
4580 case RENDERPATH_GL11:
4581 wanttangents = false;
4583 case RENDERPATH_SOFT:
4587 if (r_shownormals.integer)
4588 wanttangents = wantnormals = true;
4590 // TODO: thread this
4591 // NOTE: R_PrepareRTLights() also caches entities
4593 for (i = 0;i < r_refdef.scene.numentities;i++)
4594 if (r_refdef.viewcache.entityvisible[i])
4595 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4598 //==================================================================================
4600 static void R_View_UpdateEntityLighting (void)
4603 entity_render_t *ent;
4604 vec3_t tempdiffusenormal, avg;
4605 vec_t f, fa, fd, fdd;
4606 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4608 for (i = 0;i < r_refdef.scene.numentities;i++)
4610 ent = r_refdef.scene.entities[i];
4612 // skip unseen models
4613 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4617 if (ent->model && ent->model->brush.num_leafs)
4619 // TODO: use modellight for r_ambient settings on world?
4620 VectorSet(ent->modellight_ambient, 0, 0, 0);
4621 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4622 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4626 // fetch the lighting from the worldmodel data
4627 VectorClear(ent->modellight_ambient);
4628 VectorClear(ent->modellight_diffuse);
4629 VectorClear(tempdiffusenormal);
4630 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4633 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4635 // complete lightning for lit sprites
4636 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4637 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4639 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4640 org[2] = org[2] + r_overheadsprites_pushback.value;
4641 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4644 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4646 if(ent->flags & RENDER_EQUALIZE)
4648 // first fix up ambient lighting...
4649 if(r_equalize_entities_minambient.value > 0)
4651 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4654 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4655 if(fa < r_equalize_entities_minambient.value * fd)
4658 // fa'/fd' = minambient
4659 // fa'+0.25*fd' = fa+0.25*fd
4661 // fa' = fd' * minambient
4662 // fd'*(0.25+minambient) = fa+0.25*fd
4664 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4665 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4667 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4668 f = fdd / fd; // f>0 because all this is additive; f<1 because fdd<fd because this follows from fa < r_equalize_entities_minambient.value * fd
4669 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4670 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4675 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4677 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4678 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4682 // adjust brightness and saturation to target
4683 avg[0] = avg[1] = avg[2] = fa / f;
4684 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4685 avg[0] = avg[1] = avg[2] = fd / f;
4686 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4692 VectorSet(ent->modellight_ambient, 1, 1, 1);
4694 // move the light direction into modelspace coordinates for lighting code
4695 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4696 if(VectorLength2(ent->modellight_lightdir) == 0)
4697 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4698 VectorNormalize(ent->modellight_lightdir);
4702 #define MAX_LINEOFSIGHTTRACES 64
4704 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4707 vec3_t boxmins, boxmaxs;
4710 dp_model_t *model = r_refdef.scene.worldmodel;
4712 if (!model || !model->brush.TraceLineOfSight)
4715 // expand the box a little
4716 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4717 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4718 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4719 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4720 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4721 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4723 // return true if eye is inside enlarged box
4724 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4728 VectorCopy(eye, start);
4729 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4730 if (model->brush.TraceLineOfSight(model, start, end))
4733 // try various random positions
4734 for (i = 0;i < numsamples;i++)
4736 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4737 if (model->brush.TraceLineOfSight(model, start, end))
4745 static void R_View_UpdateEntityVisible (void)
4750 entity_render_t *ent;
4752 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4753 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4754 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
4755 : RENDER_EXTERIORMODEL;
4756 if (!r_drawviewmodel.integer)
4757 renderimask |= RENDER_VIEWMODEL;
4758 if (!r_drawexteriormodel.integer)
4759 renderimask |= RENDER_EXTERIORMODEL;
4760 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4762 // worldmodel can check visibility
4763 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4764 for (i = 0;i < r_refdef.scene.numentities;i++)
4766 ent = r_refdef.scene.entities[i];
4767 if (!(ent->flags & renderimask))
4768 if (!R_CullBox(ent->mins, ent->maxs) || (ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
4769 if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
4770 r_refdef.viewcache.entityvisible[i] = true;
4772 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4773 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4775 for (i = 0;i < r_refdef.scene.numentities;i++)
4777 ent = r_refdef.scene.entities[i];
4778 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4780 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4782 continue; // temp entities do pvs only
4783 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4784 ent->last_trace_visibility = realtime;
4785 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4786 r_refdef.viewcache.entityvisible[i] = 0;
4793 // no worldmodel or it can't check visibility
4794 for (i = 0;i < r_refdef.scene.numentities;i++)
4796 ent = r_refdef.scene.entities[i];
4797 r_refdef.viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs));
4802 /// only used if skyrendermasked, and normally returns false
4803 int R_DrawBrushModelsSky (void)
4806 entity_render_t *ent;
4809 for (i = 0;i < r_refdef.scene.numentities;i++)
4811 if (!r_refdef.viewcache.entityvisible[i])
4813 ent = r_refdef.scene.entities[i];
4814 if (!ent->model || !ent->model->DrawSky)
4816 ent->model->DrawSky(ent);
4822 static void R_DrawNoModel(entity_render_t *ent);
4823 static void R_DrawModels(void)
4826 entity_render_t *ent;
4828 for (i = 0;i < r_refdef.scene.numentities;i++)
4830 if (!r_refdef.viewcache.entityvisible[i])
4832 ent = r_refdef.scene.entities[i];
4833 r_refdef.stats.entities++;
4834 if (ent->model && ent->model->Draw != NULL)
4835 ent->model->Draw(ent);
4841 static void R_DrawModelsDepth(void)
4844 entity_render_t *ent;
4846 for (i = 0;i < r_refdef.scene.numentities;i++)
4848 if (!r_refdef.viewcache.entityvisible[i])
4850 ent = r_refdef.scene.entities[i];
4851 if (ent->model && ent->model->DrawDepth != NULL)
4852 ent->model->DrawDepth(ent);
4856 static void R_DrawModelsDebug(void)
4859 entity_render_t *ent;
4861 for (i = 0;i < r_refdef.scene.numentities;i++)
4863 if (!r_refdef.viewcache.entityvisible[i])
4865 ent = r_refdef.scene.entities[i];
4866 if (ent->model && ent->model->DrawDebug != NULL)
4867 ent->model->DrawDebug(ent);
4871 static void R_DrawModelsAddWaterPlanes(void)
4874 entity_render_t *ent;
4876 for (i = 0;i < r_refdef.scene.numentities;i++)
4878 if (!r_refdef.viewcache.entityvisible[i])
4880 ent = r_refdef.scene.entities[i];
4881 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4882 ent->model->DrawAddWaterPlanes(ent);
4886 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4888 if (r_hdr_irisadaptation.integer)
4892 vec3_t diffusenormal;
4897 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4898 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4899 brightness = max(0.0000001f, brightness);
4900 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4901 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4902 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4903 current = r_hdr_irisadaptation_value.value;
4905 current = min(current + adjust, goal);
4906 else if (current > goal)
4907 current = max(current - adjust, goal);
4908 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4909 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4911 else if (r_hdr_irisadaptation_value.value != 1.0f)
4912 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4915 static void R_View_SetFrustum(const int *scissor)
4918 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4919 vec3_t forward, left, up, origin, v;
4923 // flipped x coordinates (because x points left here)
4924 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4925 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4927 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4928 switch(vid.renderpath)
4930 case RENDERPATH_D3D9:
4931 case RENDERPATH_D3D10:
4932 case RENDERPATH_D3D11:
4933 case RENDERPATH_SOFT:
4934 // non-flipped y coordinates
4935 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4936 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4938 case RENDERPATH_GL11:
4939 case RENDERPATH_GL13:
4940 case RENDERPATH_GL20:
4941 case RENDERPATH_GLES2:
4942 // non-flipped y coordinates
4943 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4944 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4949 // we can't trust r_refdef.view.forward and friends in reflected scenes
4950 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4953 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4954 r_refdef.view.frustum[0].normal[1] = 0 - 0;
4955 r_refdef.view.frustum[0].normal[2] = -1 - 0;
4956 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4957 r_refdef.view.frustum[1].normal[1] = 0 + 0;
4958 r_refdef.view.frustum[1].normal[2] = -1 + 0;
4959 r_refdef.view.frustum[2].normal[0] = 0 - 0;
4960 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4961 r_refdef.view.frustum[2].normal[2] = -1 - 0;
4962 r_refdef.view.frustum[3].normal[0] = 0 + 0;
4963 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4964 r_refdef.view.frustum[3].normal[2] = -1 + 0;
4968 zNear = r_refdef.nearclip;
4969 nudge = 1.0 - 1.0 / (1<<23);
4970 r_refdef.view.frustum[4].normal[0] = 0 - 0;
4971 r_refdef.view.frustum[4].normal[1] = 0 - 0;
4972 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4973 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4974 r_refdef.view.frustum[5].normal[0] = 0 + 0;
4975 r_refdef.view.frustum[5].normal[1] = 0 + 0;
4976 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4977 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4983 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4984 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4985 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4986 r_refdef.view.frustum[0].dist = m[15] - m[12];
4988 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4989 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4990 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4991 r_refdef.view.frustum[1].dist = m[15] + m[12];
4993 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4994 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4995 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4996 r_refdef.view.frustum[2].dist = m[15] - m[13];
4998 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4999 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5000 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5001 r_refdef.view.frustum[3].dist = m[15] + m[13];
5003 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5004 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5005 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5006 r_refdef.view.frustum[4].dist = m[15] - m[14];
5008 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5009 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5010 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5011 r_refdef.view.frustum[5].dist = m[15] + m[14];
5014 if (r_refdef.view.useperspective)
5016 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5017 VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[0]);
5018 VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[1]);
5019 VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[2]);
5020 VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[3]);
5022 // then the normals from the corners relative to origin
5023 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5024 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5025 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5026 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5028 // in a NORMAL view, forward cross left == up
5029 // in a REFLECTED view, forward cross left == down
5030 // so our cross products above need to be adjusted for a left handed coordinate system
5031 CrossProduct(forward, left, v);
5032 if(DotProduct(v, up) < 0)
5034 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5035 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5036 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5037 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5040 // Leaving those out was a mistake, those were in the old code, and they
5041 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5042 // I couldn't reproduce it after adding those normalizations. --blub
5043 VectorNormalize(r_refdef.view.frustum[0].normal);
5044 VectorNormalize(r_refdef.view.frustum[1].normal);
5045 VectorNormalize(r_refdef.view.frustum[2].normal);
5046 VectorNormalize(r_refdef.view.frustum[3].normal);
5048 // make the corners absolute
5049 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5050 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5051 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5052 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5055 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5057 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5058 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5059 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5060 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5061 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5065 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5066 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5067 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5068 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5069 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5070 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5071 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5072 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5073 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5074 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5076 r_refdef.view.numfrustumplanes = 5;
5078 if (r_refdef.view.useclipplane)
5080 r_refdef.view.numfrustumplanes = 6;
5081 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5084 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5085 PlaneClassify(r_refdef.view.frustum + i);
5087 // LordHavoc: note to all quake engine coders, Quake had a special case
5088 // for 90 degrees which assumed a square view (wrong), so I removed it,
5089 // Quake2 has it disabled as well.
5091 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5092 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5093 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5094 //PlaneClassify(&frustum[0]);
5096 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5097 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5098 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5099 //PlaneClassify(&frustum[1]);
5101 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5102 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5103 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5104 //PlaneClassify(&frustum[2]);
5106 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5107 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5108 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5109 //PlaneClassify(&frustum[3]);
5112 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5113 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5114 //PlaneClassify(&frustum[4]);
5117 void R_View_UpdateWithScissor(const int *myscissor)
5119 R_Main_ResizeViewCache();
5120 R_View_SetFrustum(myscissor);
5121 R_View_WorldVisibility(r_refdef.view.useclipplane);
5122 R_View_UpdateEntityVisible();
5123 R_View_UpdateEntityLighting();
5126 void R_View_Update(void)
5128 R_Main_ResizeViewCache();
5129 R_View_SetFrustum(NULL);
5130 R_View_WorldVisibility(r_refdef.view.useclipplane);
5131 R_View_UpdateEntityVisible();
5132 R_View_UpdateEntityLighting();
5135 static float viewscalefpsadjusted = 1.0f;
5137 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5139 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5140 scale = bound(0.03125f, scale, 1.0f);
5141 *outwidth = (int)ceil(width * scale);
5142 *outheight = (int)ceil(height * scale);
5145 void R_Mesh_SetMainRenderTargets(void)
5147 if (r_bloomstate.fbo_framebuffer)
5148 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5150 R_Mesh_ResetRenderTargets();
5153 void R_SetupView(qboolean allowwaterclippingplane)
5155 const float *customclipplane = NULL;
5157 int scaledwidth, scaledheight;
5158 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5160 // LordHavoc: couldn't figure out how to make this approach the
5161 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5162 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5163 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5164 dist = r_refdef.view.clipplane.dist;
5165 plane[0] = r_refdef.view.clipplane.normal[0];
5166 plane[1] = r_refdef.view.clipplane.normal[1];
5167 plane[2] = r_refdef.view.clipplane.normal[2];
5169 customclipplane = plane;
5172 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5173 if (!r_refdef.view.useperspective)
5174 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, -r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip, customclipplane);
5175 else if (vid.stencil && r_useinfinitefarclip.integer)
5176 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
5178 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
5179 R_Mesh_SetMainRenderTargets();
5180 R_SetViewport(&r_refdef.view.viewport);
5183 void R_EntityMatrix(const matrix4x4_t *matrix)
5185 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5187 gl_modelmatrixchanged = false;
5188 gl_modelmatrix = *matrix;
5189 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5190 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5191 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5192 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5194 switch(vid.renderpath)
5196 case RENDERPATH_D3D9:
5198 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5199 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5202 case RENDERPATH_D3D10:
5203 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5205 case RENDERPATH_D3D11:
5206 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5208 case RENDERPATH_GL13:
5209 case RENDERPATH_GL11:
5210 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5212 case RENDERPATH_SOFT:
5213 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5214 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5216 case RENDERPATH_GL20:
5217 case RENDERPATH_GLES2:
5218 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5219 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5225 void R_ResetViewRendering2D(void)
5227 r_viewport_t viewport;
5230 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5231 R_Viewport_InitOrtho(&viewport, &identitymatrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, 0, 0, 1, 1, -10, 100, NULL);
5232 R_Mesh_ResetRenderTargets();
5233 R_SetViewport(&viewport);
5234 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5235 GL_Color(1, 1, 1, 1);
5236 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5237 GL_BlendFunc(GL_ONE, GL_ZERO);
5238 GL_ScissorTest(false);
5239 GL_DepthMask(false);
5240 GL_DepthRange(0, 1);
5241 GL_DepthTest(false);
5242 GL_DepthFunc(GL_LEQUAL);
5243 R_EntityMatrix(&identitymatrix);
5244 R_Mesh_ResetTextureState();
5245 GL_PolygonOffset(0, 0);
5246 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5247 switch(vid.renderpath)
5249 case RENDERPATH_GL11:
5250 case RENDERPATH_GL13:
5251 case RENDERPATH_GL20:
5252 case RENDERPATH_GLES2:
5253 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5255 case RENDERPATH_D3D9:
5256 case RENDERPATH_D3D10:
5257 case RENDERPATH_D3D11:
5258 case RENDERPATH_SOFT:
5261 GL_CullFace(GL_NONE);
5264 void R_ResetViewRendering3D(void)
5269 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5270 GL_Color(1, 1, 1, 1);
5271 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5272 GL_BlendFunc(GL_ONE, GL_ZERO);
5273 GL_ScissorTest(true);
5275 GL_DepthRange(0, 1);
5277 GL_DepthFunc(GL_LEQUAL);
5278 R_EntityMatrix(&identitymatrix);
5279 R_Mesh_ResetTextureState();
5280 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5281 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5282 switch(vid.renderpath)
5284 case RENDERPATH_GL11:
5285 case RENDERPATH_GL13:
5286 case RENDERPATH_GL20:
5287 case RENDERPATH_GLES2:
5288 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5290 case RENDERPATH_D3D9:
5291 case RENDERPATH_D3D10:
5292 case RENDERPATH_D3D11:
5293 case RENDERPATH_SOFT:
5296 GL_CullFace(r_refdef.view.cullface_back);
5301 R_RenderView_UpdateViewVectors
5304 static void R_RenderView_UpdateViewVectors(void)
5306 // break apart the view matrix into vectors for various purposes
5307 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5308 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5309 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5310 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5311 // make an inverted copy of the view matrix for tracking sprites
5312 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5315 void R_RenderScene(void);
5316 void R_RenderWaterPlanes(void);
5318 static void R_Water_StartFrame(void)
5321 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5322 r_waterstate_waterplane_t *p;
5324 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5327 switch(vid.renderpath)
5329 case RENDERPATH_GL20:
5330 case RENDERPATH_D3D9:
5331 case RENDERPATH_D3D10:
5332 case RENDERPATH_D3D11:
5333 case RENDERPATH_SOFT:
5334 case RENDERPATH_GLES2:
5336 case RENDERPATH_GL13:
5337 case RENDERPATH_GL11:
5341 // set waterwidth and waterheight to the water resolution that will be
5342 // used (often less than the screen resolution for faster rendering)
5343 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5344 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5346 // calculate desired texture sizes
5347 // can't use water if the card does not support the texture size
5348 if (!r_water.integer || r_showsurfaces.integer)
5349 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5350 else if (vid.support.arb_texture_non_power_of_two)
5352 texturewidth = waterwidth;
5353 textureheight = waterheight;
5354 camerawidth = waterwidth;
5355 cameraheight = waterheight;
5359 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5360 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5361 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5362 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5365 // allocate textures as needed
5366 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5368 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5369 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5371 if (p->texture_refraction)
5372 R_FreeTexture(p->texture_refraction);
5373 p->texture_refraction = NULL;
5374 if (p->texture_reflection)
5375 R_FreeTexture(p->texture_reflection);
5376 p->texture_reflection = NULL;
5377 if (p->texture_camera)
5378 R_FreeTexture(p->texture_camera);
5379 p->texture_camera = NULL;
5381 memset(&r_waterstate, 0, sizeof(r_waterstate));
5382 r_waterstate.texturewidth = texturewidth;
5383 r_waterstate.textureheight = textureheight;
5384 r_waterstate.camerawidth = camerawidth;
5385 r_waterstate.cameraheight = cameraheight;
5388 if (r_waterstate.texturewidth)
5390 r_waterstate.enabled = true;
5392 // when doing a reduced render (HDR) we want to use a smaller area
5393 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5394 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5396 // set up variables that will be used in shader setup
5397 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5398 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5399 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5400 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5403 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5404 r_waterstate.numwaterplanes = 0;
5407 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5409 int triangleindex, planeindex;
5415 r_waterstate_waterplane_t *p;
5416 texture_t *t = R_GetCurrentTexture(surface->texture);
5418 // just use the first triangle with a valid normal for any decisions
5419 VectorClear(normal);
5420 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5422 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5423 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5424 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5425 TriangleNormal(vert[0], vert[1], vert[2], normal);
5426 if (VectorLength2(normal) >= 0.001)
5430 VectorCopy(normal, plane.normal);
5431 VectorNormalize(plane.normal);
5432 plane.dist = DotProduct(vert[0], plane.normal);
5433 PlaneClassify(&plane);
5434 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5436 // skip backfaces (except if nocullface is set)
5437 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5439 VectorNegate(plane.normal, plane.normal);
5441 PlaneClassify(&plane);
5445 // find a matching plane if there is one
5446 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5447 if(p->camera_entity == t->camera_entity)
5448 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5450 if (planeindex >= r_waterstate.maxwaterplanes)
5451 return; // nothing we can do, out of planes
5453 // if this triangle does not fit any known plane rendered this frame, add one
5454 if (planeindex >= r_waterstate.numwaterplanes)
5456 // store the new plane
5457 r_waterstate.numwaterplanes++;
5459 // clear materialflags and pvs
5460 p->materialflags = 0;
5461 p->pvsvalid = false;
5462 p->camera_entity = t->camera_entity;
5463 VectorCopy(surface->mins, p->mins);
5464 VectorCopy(surface->maxs, p->maxs);
5469 p->mins[0] = min(p->mins[0], surface->mins[0]);
5470 p->mins[1] = min(p->mins[1], surface->mins[1]);
5471 p->mins[2] = min(p->mins[2], surface->mins[2]);
5472 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5473 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5474 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5476 // merge this surface's materialflags into the waterplane
5477 p->materialflags |= t->currentmaterialflags;
5478 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5480 // merge this surface's PVS into the waterplane
5481 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5482 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5483 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5485 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5491 static void R_Water_ProcessPlanes(void)
5494 r_refdef_view_t originalview;
5495 r_refdef_view_t myview;
5497 r_waterstate_waterplane_t *p;
5500 originalview = r_refdef.view;
5502 // make sure enough textures are allocated
5503 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5505 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5507 if (!p->texture_refraction)
5508 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5509 if (!p->texture_refraction)
5512 else if (p->materialflags & MATERIALFLAG_CAMERA)
5514 if (!p->texture_camera)
5515 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_camera", planeindex), r_waterstate.camerawidth, r_waterstate.cameraheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR, -1, NULL);
5516 if (!p->texture_camera)
5520 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5522 if (!p->texture_reflection)
5523 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5524 if (!p->texture_reflection)
5530 r_refdef.view = originalview;
5531 r_refdef.view.showdebug = false;
5532 r_refdef.view.width = r_waterstate.waterwidth;
5533 r_refdef.view.height = r_waterstate.waterheight;
5534 r_refdef.view.useclipplane = true;
5535 myview = r_refdef.view;
5536 r_waterstate.renderingscene = true;
5537 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5539 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5541 r_refdef.view = myview;
5542 if(r_water_scissormode.integer)
5545 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5546 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5549 // render reflected scene and copy into texture
5550 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5551 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5552 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5553 r_refdef.view.clipplane = p->plane;
5555 // reverse the cullface settings for this render
5556 r_refdef.view.cullface_front = GL_FRONT;
5557 r_refdef.view.cullface_back = GL_BACK;
5558 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5560 r_refdef.view.usecustompvs = true;
5562 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5564 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5567 R_ResetViewRendering3D();
5568 R_ClearScreen(r_refdef.fogenabled);
5569 if(r_water_scissormode.integer & 2)
5570 R_View_UpdateWithScissor(myscissor);
5573 if(r_water_scissormode.integer & 1)
5574 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5577 R_Mesh_CopyToTexture(p->texture_reflection, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5580 // render the normal view scene and copy into texture
5581 // (except that a clipping plane should be used to hide everything on one side of the water, and the viewer's weapon model should be omitted)
5582 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5584 r_refdef.view = myview;
5585 if(r_water_scissormode.integer)
5588 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5589 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5592 r_waterstate.renderingrefraction = true;
5594 r_refdef.view.clipplane = p->plane;
5595 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5596 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5598 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5600 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5601 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5602 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5603 R_RenderView_UpdateViewVectors();
5604 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5606 r_refdef.view.usecustompvs = true;
5607 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
5611 PlaneClassify(&r_refdef.view.clipplane);
5613 R_ResetViewRendering3D();
5614 R_ClearScreen(r_refdef.fogenabled);
5615 if(r_water_scissormode.integer & 2)
5616 R_View_UpdateWithScissor(myscissor);
5619 if(r_water_scissormode.integer & 1)
5620 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5623 R_Mesh_CopyToTexture(p->texture_refraction, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5624 r_waterstate.renderingrefraction = false;
5626 else if (p->materialflags & MATERIALFLAG_CAMERA)
5628 r_refdef.view = myview;
5630 r_refdef.view.clipplane = p->plane;
5631 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5632 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5634 r_refdef.view.width = r_waterstate.camerawidth;
5635 r_refdef.view.height = r_waterstate.cameraheight;
5636 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5637 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5639 if(p->camera_entity)
5641 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5642 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5645 // note: all of the view is used for displaying... so
5646 // there is no use in scissoring
5648 // reverse the cullface settings for this render
5649 r_refdef.view.cullface_front = GL_FRONT;
5650 r_refdef.view.cullface_back = GL_BACK;
5651 // also reverse the view matrix
5652 Matrix4x4_ConcatScale3(&r_refdef.view.matrix, 1, 1, -1); // this serves to invert texcoords in the result, as the copied texture is mapped the wrong way round
5653 R_RenderView_UpdateViewVectors();
5654 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5656 r_refdef.view.usecustompvs = true;
5657 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
5660 // camera needs no clipplane
5661 r_refdef.view.useclipplane = false;
5663 PlaneClassify(&r_refdef.view.clipplane);
5665 R_ResetViewRendering3D();
5666 R_ClearScreen(r_refdef.fogenabled);
5670 R_Mesh_CopyToTexture(p->texture_camera, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5671 r_waterstate.renderingrefraction = false;
5675 r_waterstate.renderingscene = false;
5676 r_refdef.view = originalview;
5677 R_ResetViewRendering3D();
5678 R_ClearScreen(r_refdef.fogenabled);
5682 r_refdef.view = originalview;
5683 r_waterstate.renderingscene = false;
5684 Cvar_SetValueQuick(&r_water, 0);
5685 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5689 void R_Bloom_StartFrame(void)
5691 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5692 int viewwidth, viewheight;
5695 if (r_viewscale_fpsscaling.integer)
5697 static double lastrealtime;
5698 double actualframetime;
5699 double targetframetime;
5701 actualframetime = realtime - lastrealtime;
5702 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5703 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5704 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5705 if (r_viewscale_fpsscaling_stepsize.value > 0)
5706 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5707 viewscalefpsadjusted += adjust;
5708 lastrealtime = realtime;
5709 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5712 viewscalefpsadjusted = 1.0f;
5714 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5716 switch(vid.renderpath)
5718 case RENDERPATH_GL20:
5719 case RENDERPATH_D3D9:
5720 case RENDERPATH_D3D10:
5721 case RENDERPATH_D3D11:
5722 case RENDERPATH_SOFT:
5723 case RENDERPATH_GLES2:
5725 case RENDERPATH_GL13:
5726 case RENDERPATH_GL11:
5730 // set bloomwidth and bloomheight to the bloom resolution that will be
5731 // used (often less than the screen resolution for faster rendering)
5732 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5733 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5734 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5735 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5736 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5738 // calculate desired texture sizes
5739 if (vid.support.arb_texture_non_power_of_two)
5741 screentexturewidth = vid.width;
5742 screentextureheight = vid.height;
5743 bloomtexturewidth = r_bloomstate.bloomwidth;
5744 bloomtextureheight = r_bloomstate.bloomheight;
5748 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
5749 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
5750 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
5751 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
5754 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))
5756 Cvar_SetValueQuick(&r_hdr, 0);
5757 Cvar_SetValueQuick(&r_bloom, 0);
5758 Cvar_SetValueQuick(&r_motionblur, 0);
5759 Cvar_SetValueQuick(&r_damageblur, 0);
5762 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)
5763 screentexturewidth = screentextureheight = 0;
5764 if (!r_hdr.integer && !r_bloom.integer)
5765 bloomtexturewidth = bloomtextureheight = 0;
5767 textype = TEXTYPE_COLORBUFFER;
5768 switch (vid.renderpath)
5770 case RENDERPATH_GL20:
5771 case RENDERPATH_GLES2:
5772 if (vid.support.ext_framebuffer_object)
5774 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5775 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5778 case RENDERPATH_D3D9:
5779 case RENDERPATH_D3D10:
5780 case RENDERPATH_D3D11:
5781 case RENDERPATH_SOFT:
5782 case RENDERPATH_GL13:
5783 case RENDERPATH_GL11:
5787 // allocate textures as needed
5788 if (r_bloomstate.screentexturewidth != screentexturewidth
5789 || r_bloomstate.screentextureheight != screentextureheight
5790 || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5791 || r_bloomstate.bloomtextureheight != bloomtextureheight
5792 || r_bloomstate.texturetype != textype
5793 || r_bloomstate.viewfbo != r_viewfbo.integer)
5795 if (r_bloomstate.texture_bloom)
5796 R_FreeTexture(r_bloomstate.texture_bloom);
5797 r_bloomstate.texture_bloom = NULL;
5798 if (r_bloomstate.texture_screen)
5799 R_FreeTexture(r_bloomstate.texture_screen);
5800 r_bloomstate.texture_screen = NULL;
5801 if (r_bloomstate.fbo_framebuffer)
5802 R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5803 r_bloomstate.fbo_framebuffer = 0;
5804 if (r_bloomstate.texture_framebuffercolor)
5805 R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5806 r_bloomstate.texture_framebuffercolor = NULL;
5807 if (r_bloomstate.texture_framebufferdepth)
5808 R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5809 r_bloomstate.texture_framebufferdepth = NULL;
5810 r_bloomstate.screentexturewidth = screentexturewidth;
5811 r_bloomstate.screentextureheight = screentextureheight;
5812 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5813 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);
5814 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5816 // FIXME: choose depth bits based on a cvar
5817 r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5818 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);
5819 r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5820 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5821 // render depth into one texture and normalmap into the other
5825 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5826 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5827 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
5828 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
5829 Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
5832 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5833 r_bloomstate.bloomtextureheight = bloomtextureheight;
5834 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5835 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);
5836 r_bloomstate.viewfbo = r_viewfbo.integer;
5837 r_bloomstate.texturetype = textype;
5840 // when doing a reduced render (HDR) we want to use a smaller area
5841 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5842 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5843 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5844 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5845 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5847 // set up a texcoord array for the full resolution screen image
5848 // (we have to keep this around to copy back during final render)
5849 r_bloomstate.screentexcoord2f[0] = 0;
5850 r_bloomstate.screentexcoord2f[1] = (float)viewheight / (float)r_bloomstate.screentextureheight;
5851 r_bloomstate.screentexcoord2f[2] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
5852 r_bloomstate.screentexcoord2f[3] = (float)viewheight / (float)r_bloomstate.screentextureheight;
5853 r_bloomstate.screentexcoord2f[4] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
5854 r_bloomstate.screentexcoord2f[5] = 0;
5855 r_bloomstate.screentexcoord2f[6] = 0;
5856 r_bloomstate.screentexcoord2f[7] = 0;
5858 // set up a texcoord array for the reduced resolution bloom image
5859 // (which will be additive blended over the screen image)
5860 r_bloomstate.bloomtexcoord2f[0] = 0;
5861 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5862 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5863 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5864 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5865 r_bloomstate.bloomtexcoord2f[5] = 0;
5866 r_bloomstate.bloomtexcoord2f[6] = 0;
5867 r_bloomstate.bloomtexcoord2f[7] = 0;
5869 switch(vid.renderpath)
5871 case RENDERPATH_GL11:
5872 case RENDERPATH_GL13:
5873 case RENDERPATH_GL20:
5874 case RENDERPATH_SOFT:
5875 case RENDERPATH_GLES2:
5877 case RENDERPATH_D3D9:
5878 case RENDERPATH_D3D10:
5879 case RENDERPATH_D3D11:
5882 for (i = 0;i < 4;i++)
5884 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5885 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5886 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5887 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5893 if (r_hdr.integer || r_bloom.integer)
5895 r_bloomstate.enabled = true;
5896 r_bloomstate.hdr = r_hdr.integer != 0;
5899 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);
5901 if (r_bloomstate.fbo_framebuffer)
5902 r_refdef.view.clear = true;
5905 void R_Bloom_CopyBloomTexture(float colorscale)
5907 r_refdef.stats.bloom++;
5909 // scale down screen texture to the bloom texture size
5911 R_Mesh_SetMainRenderTargets();
5912 R_SetViewport(&r_bloomstate.viewport);
5913 GL_BlendFunc(GL_ONE, GL_ZERO);
5914 GL_Color(colorscale, colorscale, colorscale, 1);
5915 // 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...
5916 switch(vid.renderpath)
5918 case RENDERPATH_GL11:
5919 case RENDERPATH_GL13:
5920 case RENDERPATH_GL20:
5921 case RENDERPATH_SOFT:
5922 case RENDERPATH_GLES2:
5923 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5925 case RENDERPATH_D3D9:
5926 case RENDERPATH_D3D10:
5927 case RENDERPATH_D3D11:
5928 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5931 // TODO: do boxfilter scale-down in shader?
5932 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5933 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5934 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5936 // we now have a bloom image in the framebuffer
5937 // copy it into the bloom image texture for later processing
5938 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);
5939 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5942 void R_Bloom_CopyHDRTexture(void)
5944 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);
5945 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5948 void R_Bloom_MakeTexture(void)
5951 float xoffset, yoffset, r, brighten;
5953 r_refdef.stats.bloom++;
5955 R_ResetViewRendering2D();
5957 // we have a bloom image in the framebuffer
5959 R_SetViewport(&r_bloomstate.viewport);
5961 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5964 r = bound(0, r_bloom_colorexponent.value / x, 1);
5965 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5967 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5968 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5969 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5970 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5972 // copy the vertically blurred bloom view to a texture
5973 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);
5974 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5977 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5978 brighten = r_bloom_brighten.value;
5980 brighten *= r_hdr_range.value;
5981 brighten = sqrt(brighten);
5983 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5984 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5986 for (dir = 0;dir < 2;dir++)
5988 // blend on at multiple vertical offsets to achieve a vertical blur
5989 // TODO: do offset blends using GLSL
5990 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5991 GL_BlendFunc(GL_ONE, GL_ZERO);
5992 for (x = -range;x <= range;x++)
5994 if (!dir){xoffset = 0;yoffset = x;}
5995 else {xoffset = x;yoffset = 0;}
5996 xoffset /= (float)r_bloomstate.bloomtexturewidth;
5997 yoffset /= (float)r_bloomstate.bloomtextureheight;
5998 // compute a texcoord array with the specified x and y offset
5999 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6000 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6001 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6002 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6003 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6004 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6005 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6006 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6007 // this r value looks like a 'dot' particle, fading sharply to
6008 // black at the edges
6009 // (probably not realistic but looks good enough)
6010 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6011 //r = brighten/(range*2+1);
6012 r = brighten / (range * 2 + 1);
6014 r *= (1 - x*x/(float)(range*range));
6015 GL_Color(r, r, r, 1);
6016 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6017 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6018 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6019 GL_BlendFunc(GL_ONE, GL_ONE);
6022 // copy the vertically blurred bloom view to a texture
6023 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);
6024 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6028 void R_HDR_RenderBloomTexture(void)
6030 int oldwidth, oldheight;
6031 float oldcolorscale;
6032 qboolean oldwaterstate;
6034 oldwaterstate = r_waterstate.enabled;
6035 oldcolorscale = r_refdef.view.colorscale;
6036 oldwidth = r_refdef.view.width;
6037 oldheight = r_refdef.view.height;
6038 r_refdef.view.width = r_bloomstate.bloomwidth;
6039 r_refdef.view.height = r_bloomstate.bloomheight;
6041 if(r_hdr.integer < 2)
6042 r_waterstate.enabled = false;
6044 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
6045 // TODO: add exposure compensation features
6046 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6048 r_refdef.view.showdebug = false;
6049 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6051 R_ResetViewRendering3D();
6053 R_ClearScreen(r_refdef.fogenabled);
6054 if (r_timereport_active)
6055 R_TimeReport("HDRclear");
6058 if (r_timereport_active)
6059 R_TimeReport("visibility");
6061 // only do secondary renders with HDR if r_hdr is 2 or higher
6062 r_waterstate.numwaterplanes = 0;
6063 if (r_waterstate.enabled)
6064 R_RenderWaterPlanes();
6066 r_refdef.view.showdebug = true;
6068 r_waterstate.numwaterplanes = 0;
6070 R_ResetViewRendering2D();
6072 R_Bloom_CopyHDRTexture();
6073 R_Bloom_MakeTexture();
6075 // restore the view settings
6076 r_waterstate.enabled = oldwaterstate;
6077 r_refdef.view.width = oldwidth;
6078 r_refdef.view.height = oldheight;
6079 r_refdef.view.colorscale = oldcolorscale;
6081 R_ResetViewRendering3D();
6083 R_ClearScreen(r_refdef.fogenabled);
6084 if (r_timereport_active)
6085 R_TimeReport("viewclear");
6088 static void R_BlendView(void)
6090 unsigned int permutation;
6091 float uservecs[4][4];
6093 switch (vid.renderpath)
6095 case RENDERPATH_GL20:
6096 case RENDERPATH_D3D9:
6097 case RENDERPATH_D3D10:
6098 case RENDERPATH_D3D11:
6099 case RENDERPATH_SOFT:
6100 case RENDERPATH_GLES2:
6102 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6103 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6104 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6105 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6106 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6108 if (r_bloomstate.texture_screen)
6110 // make sure the buffer is available
6111 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6113 R_ResetViewRendering2D();
6114 R_Mesh_SetMainRenderTargets();
6116 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6118 // declare variables
6120 static float avgspeed;
6122 speed = VectorLength(cl.movement_velocity);
6124 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6125 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6127 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6128 speed = bound(0, speed, 1);
6129 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6131 // calculate values into a standard alpha
6132 cl.motionbluralpha = 1 - exp(-
6134 (r_motionblur.value * speed / 80)
6136 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6139 max(0.0001, cl.time - cl.oldtime) // fps independent
6142 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6143 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6145 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6147 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6148 GL_Color(1, 1, 1, cl.motionbluralpha);
6149 switch(vid.renderpath)
6151 case RENDERPATH_GL11:
6152 case RENDERPATH_GL13:
6153 case RENDERPATH_GL20:
6154 case RENDERPATH_SOFT:
6155 case RENDERPATH_GLES2:
6156 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6158 case RENDERPATH_D3D9:
6159 case RENDERPATH_D3D10:
6160 case RENDERPATH_D3D11:
6161 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6164 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6165 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6166 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6170 // copy view into the screen texture
6171 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);
6172 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6174 else if (!r_bloomstate.texture_bloom)
6176 // we may still have to do view tint...
6177 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6179 // apply a color tint to the whole view
6180 R_ResetViewRendering2D();
6181 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6182 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6183 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6184 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6185 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6187 break; // no screen processing, no bloom, skip it
6190 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6192 // render simple bloom effect
6193 // copy the screen and shrink it and darken it for the bloom process
6194 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6195 // make the bloom texture
6196 R_Bloom_MakeTexture();
6199 #if _MSC_VER >= 1400
6200 #define sscanf sscanf_s
6202 memset(uservecs, 0, sizeof(uservecs));
6203 if (r_glsl_postprocess_uservec1_enable.integer)
6204 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6205 if (r_glsl_postprocess_uservec2_enable.integer)
6206 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6207 if (r_glsl_postprocess_uservec3_enable.integer)
6208 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6209 if (r_glsl_postprocess_uservec4_enable.integer)
6210 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6212 R_ResetViewRendering2D();
6213 GL_Color(1, 1, 1, 1);
6214 GL_BlendFunc(GL_ONE, GL_ZERO);
6216 switch(vid.renderpath)
6218 case RENDERPATH_GL20:
6219 case RENDERPATH_GLES2:
6220 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6221 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6222 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6223 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6224 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6225 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]);
6226 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6227 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]);
6228 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]);
6229 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]);
6230 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]);
6231 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6232 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6233 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);
6235 case RENDERPATH_D3D9:
6237 // 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...
6238 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6239 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6240 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6241 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6242 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6243 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6244 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6245 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6246 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6247 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6248 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6249 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6250 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6251 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6254 case RENDERPATH_D3D10:
6255 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6257 case RENDERPATH_D3D11:
6258 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6260 case RENDERPATH_SOFT:
6261 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6262 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6263 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6264 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6265 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6266 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6267 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6268 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6269 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6270 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6271 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6272 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6273 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6274 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6279 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6280 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6282 case RENDERPATH_GL13:
6283 case RENDERPATH_GL11:
6284 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6286 // apply a color tint to the whole view
6287 R_ResetViewRendering2D();
6288 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6289 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6290 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6291 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6292 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6298 matrix4x4_t r_waterscrollmatrix;
6300 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6302 if (r_refdef.fog_density)
6304 r_refdef.fogcolor[0] = r_refdef.fog_red;
6305 r_refdef.fogcolor[1] = r_refdef.fog_green;
6306 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6308 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6309 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6310 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6311 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6315 VectorCopy(r_refdef.fogcolor, fogvec);
6316 // color.rgb *= ContrastBoost * SceneBrightness;
6317 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6318 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6319 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6320 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6325 void R_UpdateVariables(void)
6329 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6331 r_refdef.farclip = r_farclip_base.value;
6332 if (r_refdef.scene.worldmodel)
6333 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6334 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6336 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6337 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6338 r_refdef.polygonfactor = 0;
6339 r_refdef.polygonoffset = 0;
6340 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6341 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6343 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6344 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6345 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6346 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6347 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6348 if (FAKELIGHT_ENABLED)
6350 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6352 if (r_showsurfaces.integer)
6354 r_refdef.scene.rtworld = false;
6355 r_refdef.scene.rtworldshadows = false;
6356 r_refdef.scene.rtdlight = false;
6357 r_refdef.scene.rtdlightshadows = false;
6358 r_refdef.lightmapintensity = 0;
6361 if (gamemode == GAME_NEHAHRA)
6363 if (gl_fogenable.integer)
6365 r_refdef.oldgl_fogenable = true;
6366 r_refdef.fog_density = gl_fogdensity.value;
6367 r_refdef.fog_red = gl_fogred.value;
6368 r_refdef.fog_green = gl_foggreen.value;
6369 r_refdef.fog_blue = gl_fogblue.value;
6370 r_refdef.fog_alpha = 1;
6371 r_refdef.fog_start = 0;
6372 r_refdef.fog_end = gl_skyclip.value;
6373 r_refdef.fog_height = 1<<30;
6374 r_refdef.fog_fadedepth = 128;
6376 else if (r_refdef.oldgl_fogenable)
6378 r_refdef.oldgl_fogenable = false;
6379 r_refdef.fog_density = 0;
6380 r_refdef.fog_red = 0;
6381 r_refdef.fog_green = 0;
6382 r_refdef.fog_blue = 0;
6383 r_refdef.fog_alpha = 0;
6384 r_refdef.fog_start = 0;
6385 r_refdef.fog_end = 0;
6386 r_refdef.fog_height = 1<<30;
6387 r_refdef.fog_fadedepth = 128;
6391 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6392 r_refdef.fog_start = max(0, r_refdef.fog_start);
6393 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6395 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6397 if (r_refdef.fog_density && r_drawfog.integer)
6399 r_refdef.fogenabled = true;
6400 // this is the point where the fog reaches 0.9986 alpha, which we
6401 // consider a good enough cutoff point for the texture
6402 // (0.9986 * 256 == 255.6)
6403 if (r_fog_exp2.integer)
6404 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6406 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6407 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6408 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6409 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6410 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6411 R_BuildFogHeightTexture();
6412 // fog color was already set
6413 // update the fog texture
6414 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)
6415 R_BuildFogTexture();
6416 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6417 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6420 r_refdef.fogenabled = false;
6422 switch(vid.renderpath)
6424 case RENDERPATH_GL20:
6425 case RENDERPATH_D3D9:
6426 case RENDERPATH_D3D10:
6427 case RENDERPATH_D3D11:
6428 case RENDERPATH_SOFT:
6429 case RENDERPATH_GLES2:
6430 if(v_glslgamma.integer && !vid_gammatables_trivial)
6432 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6434 // build GLSL gamma texture
6435 #define RAMPWIDTH 256
6436 unsigned short ramp[RAMPWIDTH * 3];
6437 unsigned char rampbgr[RAMPWIDTH][4];
6440 r_texture_gammaramps_serial = vid_gammatables_serial;
6442 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6443 for(i = 0; i < RAMPWIDTH; ++i)
6445 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6446 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6447 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6450 if (r_texture_gammaramps)
6452 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6456 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6462 // remove GLSL gamma texture
6465 case RENDERPATH_GL13:
6466 case RENDERPATH_GL11:
6471 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6472 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6478 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6479 if( scenetype != r_currentscenetype ) {
6480 // store the old scenetype
6481 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6482 r_currentscenetype = scenetype;
6483 // move in the new scene
6484 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6493 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6495 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6496 if( scenetype == r_currentscenetype ) {
6497 return &r_refdef.scene;
6499 return &r_scenes_store[ scenetype ];
6508 int dpsoftrast_test;
6509 void R_RenderView(void)
6511 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6513 dpsoftrast_test = r_test.integer;
6515 if (r_timereport_active)
6516 R_TimeReport("start");
6517 r_textureframe++; // used only by R_GetCurrentTexture
6518 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6520 if(R_CompileShader_CheckStaticParms())
6523 if (!r_drawentities.integer)
6524 r_refdef.scene.numentities = 0;
6526 R_AnimCache_ClearCache();
6527 R_FrameData_NewFrame();
6529 /* adjust for stereo display */
6530 if(R_Stereo_Active())
6532 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);
6533 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6536 if (r_refdef.view.isoverlay)
6538 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6539 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6540 R_TimeReport("depthclear");
6542 r_refdef.view.showdebug = false;
6544 r_waterstate.enabled = false;
6545 r_waterstate.numwaterplanes = 0;
6549 r_refdef.view.matrix = originalmatrix;
6555 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6557 r_refdef.view.matrix = originalmatrix;
6558 return; //Host_Error ("R_RenderView: NULL worldmodel");
6561 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6563 R_RenderView_UpdateViewVectors();
6565 R_Shadow_UpdateWorldLightSelection();
6567 R_Bloom_StartFrame();
6568 R_Water_StartFrame();
6571 if (r_timereport_active)
6572 R_TimeReport("viewsetup");
6574 R_ResetViewRendering3D();
6576 if (r_refdef.view.clear || r_refdef.fogenabled)
6578 R_ClearScreen(r_refdef.fogenabled);
6579 if (r_timereport_active)
6580 R_TimeReport("viewclear");
6582 r_refdef.view.clear = true;
6584 // this produces a bloom texture to be used in R_BlendView() later
6585 if (r_hdr.integer && r_bloomstate.bloomwidth)
6587 R_HDR_RenderBloomTexture();
6588 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6589 r_textureframe++; // used only by R_GetCurrentTexture
6592 r_refdef.view.showdebug = true;
6595 if (r_timereport_active)
6596 R_TimeReport("visibility");
6598 r_waterstate.numwaterplanes = 0;
6599 if (r_waterstate.enabled)
6600 R_RenderWaterPlanes();
6603 r_waterstate.numwaterplanes = 0;
6606 if (r_timereport_active)
6607 R_TimeReport("blendview");
6609 GL_Scissor(0, 0, vid.width, vid.height);
6610 GL_ScissorTest(false);
6612 r_refdef.view.matrix = originalmatrix;
6617 void R_RenderWaterPlanes(void)
6619 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6621 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6622 if (r_timereport_active)
6623 R_TimeReport("waterworld");
6626 // don't let sound skip if going slow
6627 if (r_refdef.scene.extraupdate)
6630 R_DrawModelsAddWaterPlanes();
6631 if (r_timereport_active)
6632 R_TimeReport("watermodels");
6634 if (r_waterstate.numwaterplanes)
6636 R_Water_ProcessPlanes();
6637 if (r_timereport_active)
6638 R_TimeReport("waterscenes");
6642 extern void R_DrawLightningBeams (void);
6643 extern void VM_CL_AddPolygonsToMeshQueue (void);
6644 extern void R_DrawPortals (void);
6645 extern cvar_t cl_locs_show;
6646 static void R_DrawLocs(void);
6647 static void R_DrawEntityBBoxes(void);
6648 static void R_DrawModelDecals(void);
6649 extern void R_DrawModelShadows(void);
6650 extern void R_DrawModelShadowMaps(void);
6651 extern cvar_t cl_decals_newsystem;
6652 extern qboolean r_shadow_usingdeferredprepass;
6653 void R_RenderScene(void)
6655 qboolean shadowmapping = false;
6657 if (r_timereport_active)
6658 R_TimeReport("beginscene");
6660 r_refdef.stats.renders++;
6664 // don't let sound skip if going slow
6665 if (r_refdef.scene.extraupdate)
6668 R_MeshQueue_BeginScene();
6672 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);
6674 if (r_timereport_active)
6675 R_TimeReport("skystartframe");
6677 if (cl.csqc_vidvars.drawworld)
6679 // don't let sound skip if going slow
6680 if (r_refdef.scene.extraupdate)
6683 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6685 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6686 if (r_timereport_active)
6687 R_TimeReport("worldsky");
6690 if (R_DrawBrushModelsSky() && r_timereport_active)
6691 R_TimeReport("bmodelsky");
6693 if (skyrendermasked && skyrenderlater)
6695 // we have to force off the water clipping plane while rendering sky
6699 if (r_timereport_active)
6700 R_TimeReport("sky");
6704 R_AnimCache_CacheVisibleEntities();
6705 if (r_timereport_active)
6706 R_TimeReport("animation");
6708 R_Shadow_PrepareLights();
6709 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6710 R_Shadow_PrepareModelShadows();
6711 if (r_timereport_active)
6712 R_TimeReport("preparelights");
6714 if (R_Shadow_ShadowMappingEnabled())
6715 shadowmapping = true;
6717 if (r_shadow_usingdeferredprepass)
6718 R_Shadow_DrawPrepass();
6720 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6722 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6723 if (r_timereport_active)
6724 R_TimeReport("worlddepth");
6726 if (r_depthfirst.integer >= 2)
6728 R_DrawModelsDepth();
6729 if (r_timereport_active)
6730 R_TimeReport("modeldepth");
6733 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6735 R_DrawModelShadowMaps();
6736 R_ResetViewRendering3D();
6737 // don't let sound skip if going slow
6738 if (r_refdef.scene.extraupdate)
6742 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6744 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6745 if (r_timereport_active)
6746 R_TimeReport("world");
6749 // don't let sound skip if going slow
6750 if (r_refdef.scene.extraupdate)
6754 if (r_timereport_active)
6755 R_TimeReport("models");
6757 // don't let sound skip if going slow
6758 if (r_refdef.scene.extraupdate)
6761 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6763 R_DrawModelShadows();
6764 R_ResetViewRendering3D();
6765 // don't let sound skip if going slow
6766 if (r_refdef.scene.extraupdate)
6770 if (!r_shadow_usingdeferredprepass)
6772 R_Shadow_DrawLights();
6773 if (r_timereport_active)
6774 R_TimeReport("rtlights");
6777 // don't let sound skip if going slow
6778 if (r_refdef.scene.extraupdate)
6781 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6783 R_DrawModelShadows();
6784 R_ResetViewRendering3D();
6785 // don't let sound skip if going slow
6786 if (r_refdef.scene.extraupdate)
6790 if (cl.csqc_vidvars.drawworld)
6792 if (cl_decals_newsystem.integer)
6794 R_DrawModelDecals();
6795 if (r_timereport_active)
6796 R_TimeReport("modeldecals");
6801 if (r_timereport_active)
6802 R_TimeReport("decals");
6806 if (r_timereport_active)
6807 R_TimeReport("particles");
6810 if (r_timereport_active)
6811 R_TimeReport("explosions");
6813 R_DrawLightningBeams();
6814 if (r_timereport_active)
6815 R_TimeReport("lightning");
6818 VM_CL_AddPolygonsToMeshQueue();
6820 if (r_refdef.view.showdebug)
6822 if (cl_locs_show.integer)
6825 if (r_timereport_active)
6826 R_TimeReport("showlocs");
6829 if (r_drawportals.integer)
6832 if (r_timereport_active)
6833 R_TimeReport("portals");
6836 if (r_showbboxes.value > 0)
6838 R_DrawEntityBBoxes();
6839 if (r_timereport_active)
6840 R_TimeReport("bboxes");
6844 R_MeshQueue_RenderTransparent();
6845 if (r_timereport_active)
6846 R_TimeReport("drawtrans");
6848 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))
6850 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6851 if (r_timereport_active)
6852 R_TimeReport("worlddebug");
6853 R_DrawModelsDebug();
6854 if (r_timereport_active)
6855 R_TimeReport("modeldebug");
6858 if (cl.csqc_vidvars.drawworld)
6860 R_Shadow_DrawCoronas();
6861 if (r_timereport_active)
6862 R_TimeReport("coronas");
6867 GL_DepthTest(false);
6868 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6869 GL_Color(1, 1, 1, 1);
6870 qglBegin(GL_POLYGON);
6871 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6872 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6873 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6874 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6876 qglBegin(GL_POLYGON);
6877 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]);
6878 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]);
6879 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]);
6880 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]);
6882 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6886 // don't let sound skip if going slow
6887 if (r_refdef.scene.extraupdate)
6890 R_ResetViewRendering2D();
6893 static const unsigned short bboxelements[36] =
6903 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6906 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6908 RSurf_ActiveWorldEntity();
6910 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6911 GL_DepthMask(false);
6912 GL_DepthRange(0, 1);
6913 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6914 // R_Mesh_ResetTextureState();
6916 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6917 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6918 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6919 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6920 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6921 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6922 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6923 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6924 R_FillColors(color4f, 8, cr, cg, cb, ca);
6925 if (r_refdef.fogenabled)
6927 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6929 f1 = RSurf_FogVertex(v);
6931 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6932 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6933 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6936 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6937 R_Mesh_ResetTextureState();
6938 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6939 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6942 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6946 prvm_edict_t *edict;
6947 prvm_prog_t *prog_save = prog;
6949 // this function draws bounding boxes of server entities
6953 GL_CullFace(GL_NONE);
6954 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6958 for (i = 0;i < numsurfaces;i++)
6960 edict = PRVM_EDICT_NUM(surfacelist[i]);
6961 switch ((int)edict->fields.server->solid)
6963 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
6964 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
6965 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
6966 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6967 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
6968 default: Vector4Set(color, 0, 0, 0, 0.50);break;
6970 color[3] *= r_showbboxes.value;
6971 color[3] = bound(0, color[3], 1);
6972 GL_DepthTest(!r_showdisabledepthtest.integer);
6973 GL_CullFace(r_refdef.view.cullface_front);
6974 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6980 static void R_DrawEntityBBoxes(void)
6983 prvm_edict_t *edict;
6985 prvm_prog_t *prog_save = prog;
6987 // this function draws bounding boxes of server entities
6993 for (i = 0;i < prog->num_edicts;i++)
6995 edict = PRVM_EDICT_NUM(i);
6996 if (edict->priv.server->free)
6998 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6999 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
7001 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
7003 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7004 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7010 static const int nomodelelement3i[24] =
7022 static const unsigned short nomodelelement3s[24] =
7034 static const float nomodelvertex3f[6*3] =
7044 static const float nomodelcolor4f[6*4] =
7046 0.0f, 0.0f, 0.5f, 1.0f,
7047 0.0f, 0.0f, 0.5f, 1.0f,
7048 0.0f, 0.5f, 0.0f, 1.0f,
7049 0.0f, 0.5f, 0.0f, 1.0f,
7050 0.5f, 0.0f, 0.0f, 1.0f,
7051 0.5f, 0.0f, 0.0f, 1.0f
7054 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7060 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);
7062 // this is only called once per entity so numsurfaces is always 1, and
7063 // surfacelist is always {0}, so this code does not handle batches
7065 if (rsurface.ent_flags & RENDER_ADDITIVE)
7067 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7068 GL_DepthMask(false);
7070 else if (rsurface.colormod[3] < 1)
7072 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7073 GL_DepthMask(false);
7077 GL_BlendFunc(GL_ONE, GL_ZERO);
7080 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7081 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7082 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7083 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7084 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7085 for (i = 0, c = color4f;i < 6;i++, c += 4)
7087 c[0] *= rsurface.colormod[0];
7088 c[1] *= rsurface.colormod[1];
7089 c[2] *= rsurface.colormod[2];
7090 c[3] *= rsurface.colormod[3];
7092 if (r_refdef.fogenabled)
7094 for (i = 0, c = color4f;i < 6;i++, c += 4)
7096 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7098 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7099 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7100 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7103 // R_Mesh_ResetTextureState();
7104 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7105 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7106 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7109 void R_DrawNoModel(entity_render_t *ent)
7112 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7113 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7114 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7116 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7119 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7121 vec3_t right1, right2, diff, normal;
7123 VectorSubtract (org2, org1, normal);
7125 // calculate 'right' vector for start
7126 VectorSubtract (r_refdef.view.origin, org1, diff);
7127 CrossProduct (normal, diff, right1);
7128 VectorNormalize (right1);
7130 // calculate 'right' vector for end
7131 VectorSubtract (r_refdef.view.origin, org2, diff);
7132 CrossProduct (normal, diff, right2);
7133 VectorNormalize (right2);
7135 vert[ 0] = org1[0] + width * right1[0];
7136 vert[ 1] = org1[1] + width * right1[1];
7137 vert[ 2] = org1[2] + width * right1[2];
7138 vert[ 3] = org1[0] - width * right1[0];
7139 vert[ 4] = org1[1] - width * right1[1];
7140 vert[ 5] = org1[2] - width * right1[2];
7141 vert[ 6] = org2[0] - width * right2[0];
7142 vert[ 7] = org2[1] - width * right2[1];
7143 vert[ 8] = org2[2] - width * right2[2];
7144 vert[ 9] = org2[0] + width * right2[0];
7145 vert[10] = org2[1] + width * right2[1];
7146 vert[11] = org2[2] + width * right2[2];
7149 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)
7151 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7152 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7153 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7154 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7155 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7156 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7157 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7158 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7159 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7160 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7161 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7162 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7165 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7170 VectorSet(v, x, y, z);
7171 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7172 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7174 if (i == mesh->numvertices)
7176 if (mesh->numvertices < mesh->maxvertices)
7178 VectorCopy(v, vertex3f);
7179 mesh->numvertices++;
7181 return mesh->numvertices;
7187 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7191 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7192 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7193 e = mesh->element3i + mesh->numtriangles * 3;
7194 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7196 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7197 if (mesh->numtriangles < mesh->maxtriangles)
7202 mesh->numtriangles++;
7204 element[1] = element[2];
7208 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7212 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7213 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7214 e = mesh->element3i + mesh->numtriangles * 3;
7215 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7217 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7218 if (mesh->numtriangles < mesh->maxtriangles)
7223 mesh->numtriangles++;
7225 element[1] = element[2];
7229 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7230 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7232 int planenum, planenum2;
7235 mplane_t *plane, *plane2;
7237 double temppoints[2][256*3];
7238 // figure out how large a bounding box we need to properly compute this brush
7240 for (w = 0;w < numplanes;w++)
7241 maxdist = max(maxdist, fabs(planes[w].dist));
7242 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7243 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7244 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7248 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7249 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7251 if (planenum2 == planenum)
7253 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);
7256 if (tempnumpoints < 3)
7258 // generate elements forming a triangle fan for this polygon
7259 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7263 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)
7265 texturelayer_t *layer;
7266 layer = t->currentlayers + t->currentnumlayers++;
7268 layer->depthmask = depthmask;
7269 layer->blendfunc1 = blendfunc1;
7270 layer->blendfunc2 = blendfunc2;
7271 layer->texture = texture;
7272 layer->texmatrix = *matrix;
7273 layer->color[0] = r;
7274 layer->color[1] = g;
7275 layer->color[2] = b;
7276 layer->color[3] = a;
7279 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7281 if(parms[0] == 0 && parms[1] == 0)
7283 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7284 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7289 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7292 index = parms[2] + r_refdef.scene.time * parms[3];
7293 index -= floor(index);
7294 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7297 case Q3WAVEFUNC_NONE:
7298 case Q3WAVEFUNC_NOISE:
7299 case Q3WAVEFUNC_COUNT:
7302 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7303 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7304 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7305 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7306 case Q3WAVEFUNC_TRIANGLE:
7308 f = index - floor(index);
7319 f = parms[0] + parms[1] * f;
7320 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7321 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7325 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7330 matrix4x4_t matrix, temp;
7331 switch(tcmod->tcmod)
7335 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7336 matrix = r_waterscrollmatrix;
7338 matrix = identitymatrix;
7340 case Q3TCMOD_ENTITYTRANSLATE:
7341 // this is used in Q3 to allow the gamecode to control texcoord
7342 // scrolling on the entity, which is not supported in darkplaces yet.
7343 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7345 case Q3TCMOD_ROTATE:
7346 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7347 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7348 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7351 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7353 case Q3TCMOD_SCROLL:
7354 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7356 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7357 w = (int) tcmod->parms[0];
7358 h = (int) tcmod->parms[1];
7359 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7361 idx = (int) floor(f * w * h);
7362 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7364 case Q3TCMOD_STRETCH:
7365 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7366 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7368 case Q3TCMOD_TRANSFORM:
7369 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7370 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7371 VectorSet(tcmat + 6, 0 , 0 , 1);
7372 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7373 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7375 case Q3TCMOD_TURBULENT:
7376 // this is handled in the RSurf_PrepareVertices function
7377 matrix = identitymatrix;
7381 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7384 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7386 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7387 char name[MAX_QPATH];
7388 skinframe_t *skinframe;
7389 unsigned char pixels[296*194];
7390 strlcpy(cache->name, skinname, sizeof(cache->name));
7391 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7392 if (developer_loading.integer)
7393 Con_Printf("loading %s\n", name);
7394 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7395 if (!skinframe || !skinframe->base)
7398 fs_offset_t filesize;
7400 f = FS_LoadFile(name, tempmempool, true, &filesize);
7403 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7404 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7408 cache->skinframe = skinframe;
7411 texture_t *R_GetCurrentTexture(texture_t *t)
7414 const entity_render_t *ent = rsurface.entity;
7415 dp_model_t *model = ent->model;
7416 q3shaderinfo_layer_tcmod_t *tcmod;
7418 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7419 return t->currentframe;
7420 t->update_lastrenderframe = r_textureframe;
7421 t->update_lastrenderentity = (void *)ent;
7423 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7424 t->camera_entity = ent->entitynumber;
7426 t->camera_entity = 0;
7428 // switch to an alternate material if this is a q1bsp animated material
7430 texture_t *texture = t;
7431 int s = rsurface.ent_skinnum;
7432 if ((unsigned int)s >= (unsigned int)model->numskins)
7434 if (model->skinscenes)
7436 if (model->skinscenes[s].framecount > 1)
7437 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7439 s = model->skinscenes[s].firstframe;
7442 t = t + s * model->num_surfaces;
7445 // use an alternate animation if the entity's frame is not 0,
7446 // and only if the texture has an alternate animation
7447 if (rsurface.ent_alttextures && t->anim_total[1])
7448 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7450 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7452 texture->currentframe = t;
7455 // update currentskinframe to be a qw skin or animation frame
7456 if (rsurface.ent_qwskin >= 0)
7458 i = rsurface.ent_qwskin;
7459 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7461 r_qwskincache_size = cl.maxclients;
7463 Mem_Free(r_qwskincache);
7464 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7466 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7467 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7468 t->currentskinframe = r_qwskincache[i].skinframe;
7469 if (t->currentskinframe == NULL)
7470 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7472 else if (t->numskinframes >= 2)
7473 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7474 if (t->backgroundnumskinframes >= 2)
7475 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7477 t->currentmaterialflags = t->basematerialflags;
7478 t->currentalpha = rsurface.colormod[3];
7479 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7480 t->currentalpha *= r_wateralpha.value;
7481 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7482 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7483 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7484 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7485 if (!(rsurface.ent_flags & RENDER_LIGHT))
7486 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7487 else if (FAKELIGHT_ENABLED)
7489 // no modellight if using fakelight for the map
7491 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7493 // pick a model lighting mode
7494 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7495 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7497 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7499 if (rsurface.ent_flags & RENDER_ADDITIVE)
7500 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7501 else if (t->currentalpha < 1)
7502 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7503 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7504 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7505 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7506 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7507 if (t->backgroundnumskinframes)
7508 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7509 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7511 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7512 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7515 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7516 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7517 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7519 // there is no tcmod
7520 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7522 t->currenttexmatrix = r_waterscrollmatrix;
7523 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7525 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7527 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7528 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7531 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7532 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7533 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7534 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7536 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7537 if (t->currentskinframe->qpixels)
7538 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7539 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7540 if (!t->basetexture)
7541 t->basetexture = r_texture_notexture;
7542 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7543 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7544 t->nmaptexture = t->currentskinframe->nmap;
7545 if (!t->nmaptexture)
7546 t->nmaptexture = r_texture_blanknormalmap;
7547 t->glosstexture = r_texture_black;
7548 t->glowtexture = t->currentskinframe->glow;
7549 t->fogtexture = t->currentskinframe->fog;
7550 t->reflectmasktexture = t->currentskinframe->reflect;
7551 if (t->backgroundnumskinframes)
7553 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7554 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7555 t->backgroundglosstexture = r_texture_black;
7556 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7557 if (!t->backgroundnmaptexture)
7558 t->backgroundnmaptexture = r_texture_blanknormalmap;
7562 t->backgroundbasetexture = r_texture_white;
7563 t->backgroundnmaptexture = r_texture_blanknormalmap;
7564 t->backgroundglosstexture = r_texture_black;
7565 t->backgroundglowtexture = NULL;
7567 t->specularpower = r_shadow_glossexponent.value;
7568 // TODO: store reference values for these in the texture?
7569 t->specularscale = 0;
7570 if (r_shadow_gloss.integer > 0)
7572 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7574 if (r_shadow_glossintensity.value > 0)
7576 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7577 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7578 t->specularscale = r_shadow_glossintensity.value;
7581 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7583 t->glosstexture = r_texture_white;
7584 t->backgroundglosstexture = r_texture_white;
7585 t->specularscale = r_shadow_gloss2intensity.value;
7586 t->specularpower = r_shadow_gloss2exponent.value;
7589 t->specularscale *= t->specularscalemod;
7590 t->specularpower *= t->specularpowermod;
7592 // lightmaps mode looks bad with dlights using actual texturing, so turn
7593 // off the colormap and glossmap, but leave the normalmap on as it still
7594 // accurately represents the shading involved
7595 if (gl_lightmaps.integer)
7597 t->basetexture = r_texture_grey128;
7598 t->pantstexture = r_texture_black;
7599 t->shirttexture = r_texture_black;
7600 t->nmaptexture = r_texture_blanknormalmap;
7601 t->glosstexture = r_texture_black;
7602 t->glowtexture = NULL;
7603 t->fogtexture = NULL;
7604 t->reflectmasktexture = NULL;
7605 t->backgroundbasetexture = NULL;
7606 t->backgroundnmaptexture = r_texture_blanknormalmap;
7607 t->backgroundglosstexture = r_texture_black;
7608 t->backgroundglowtexture = NULL;
7609 t->specularscale = 0;
7610 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7613 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7614 VectorClear(t->dlightcolor);
7615 t->currentnumlayers = 0;
7616 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7618 int blendfunc1, blendfunc2;
7620 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7622 blendfunc1 = GL_SRC_ALPHA;
7623 blendfunc2 = GL_ONE;
7625 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7627 blendfunc1 = GL_SRC_ALPHA;
7628 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7630 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7632 blendfunc1 = t->customblendfunc[0];
7633 blendfunc2 = t->customblendfunc[1];
7637 blendfunc1 = GL_ONE;
7638 blendfunc2 = GL_ZERO;
7640 // don't colormod evilblend textures
7641 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7642 VectorSet(t->lightmapcolor, 1, 1, 1);
7643 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7644 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7646 // fullbright is not affected by r_refdef.lightmapintensity
7647 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]);
7648 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7649 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]);
7650 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7651 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]);
7655 vec3_t ambientcolor;
7657 // set the color tint used for lights affecting this surface
7658 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7660 // q3bsp has no lightmap updates, so the lightstylevalue that
7661 // would normally be baked into the lightmap must be
7662 // applied to the color
7663 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7664 if (model->type == mod_brushq3)
7665 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7666 colorscale *= r_refdef.lightmapintensity;
7667 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7668 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7669 // basic lit geometry
7670 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]);
7671 // add pants/shirt if needed
7672 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7673 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]);
7674 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7675 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]);
7676 // now add ambient passes if needed
7677 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7679 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]);
7680 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7681 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]);
7682 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7683 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]);
7686 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7687 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]);
7688 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7690 // if this is opaque use alpha blend which will darken the earlier
7693 // if this is an alpha blended material, all the earlier passes
7694 // were darkened by fog already, so we only need to add the fog
7695 // color ontop through the fog mask texture
7697 // if this is an additive blended material, all the earlier passes
7698 // were darkened by fog already, and we should not add fog color
7699 // (because the background was not darkened, there is no fog color
7700 // that was lost behind it).
7701 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]);
7705 return t->currentframe;
7708 rsurfacestate_t rsurface;
7710 void RSurf_ActiveWorldEntity(void)
7712 dp_model_t *model = r_refdef.scene.worldmodel;
7713 //if (rsurface.entity == r_refdef.scene.worldentity)
7715 rsurface.entity = r_refdef.scene.worldentity;
7716 rsurface.skeleton = NULL;
7717 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7718 rsurface.ent_skinnum = 0;
7719 rsurface.ent_qwskin = -1;
7720 rsurface.ent_shadertime = 0;
7721 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7722 rsurface.matrix = identitymatrix;
7723 rsurface.inversematrix = identitymatrix;
7724 rsurface.matrixscale = 1;
7725 rsurface.inversematrixscale = 1;
7726 R_EntityMatrix(&identitymatrix);
7727 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7728 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7729 rsurface.fograngerecip = r_refdef.fograngerecip;
7730 rsurface.fogheightfade = r_refdef.fogheightfade;
7731 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7732 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7733 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7734 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7735 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7736 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7737 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7738 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7739 rsurface.colormod[3] = 1;
7740 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);
7741 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7742 rsurface.frameblend[0].lerp = 1;
7743 rsurface.ent_alttextures = false;
7744 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7745 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7746 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7747 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7748 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7749 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7750 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7751 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7752 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7753 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7754 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7755 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7756 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7757 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7758 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7759 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7760 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7761 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7762 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7763 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7764 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7765 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7766 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7767 rsurface.modelelement3i = model->surfmesh.data_element3i;
7768 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7769 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7770 rsurface.modelelement3s = model->surfmesh.data_element3s;
7771 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7772 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7773 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7774 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7775 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7776 rsurface.modelsurfaces = model->data_surfaces;
7777 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7778 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7779 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7780 rsurface.modelgeneratedvertex = false;
7781 rsurface.batchgeneratedvertex = false;
7782 rsurface.batchfirstvertex = 0;
7783 rsurface.batchnumvertices = 0;
7784 rsurface.batchfirsttriangle = 0;
7785 rsurface.batchnumtriangles = 0;
7786 rsurface.batchvertex3f = NULL;
7787 rsurface.batchvertex3f_vertexbuffer = NULL;
7788 rsurface.batchvertex3f_bufferoffset = 0;
7789 rsurface.batchsvector3f = NULL;
7790 rsurface.batchsvector3f_vertexbuffer = NULL;
7791 rsurface.batchsvector3f_bufferoffset = 0;
7792 rsurface.batchtvector3f = NULL;
7793 rsurface.batchtvector3f_vertexbuffer = NULL;
7794 rsurface.batchtvector3f_bufferoffset = 0;
7795 rsurface.batchnormal3f = NULL;
7796 rsurface.batchnormal3f_vertexbuffer = NULL;
7797 rsurface.batchnormal3f_bufferoffset = 0;
7798 rsurface.batchlightmapcolor4f = NULL;
7799 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7800 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7801 rsurface.batchtexcoordtexture2f = NULL;
7802 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7803 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7804 rsurface.batchtexcoordlightmap2f = NULL;
7805 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7806 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7807 rsurface.batchvertexmesh = NULL;
7808 rsurface.batchvertexmeshbuffer = NULL;
7809 rsurface.batchvertex3fbuffer = NULL;
7810 rsurface.batchelement3i = NULL;
7811 rsurface.batchelement3i_indexbuffer = NULL;
7812 rsurface.batchelement3i_bufferoffset = 0;
7813 rsurface.batchelement3s = NULL;
7814 rsurface.batchelement3s_indexbuffer = NULL;
7815 rsurface.batchelement3s_bufferoffset = 0;
7816 rsurface.passcolor4f = NULL;
7817 rsurface.passcolor4f_vertexbuffer = NULL;
7818 rsurface.passcolor4f_bufferoffset = 0;
7821 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7823 dp_model_t *model = ent->model;
7824 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7826 rsurface.entity = (entity_render_t *)ent;
7827 rsurface.skeleton = ent->skeleton;
7828 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7829 rsurface.ent_skinnum = ent->skinnum;
7830 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;
7831 rsurface.ent_shadertime = ent->shadertime;
7832 rsurface.ent_flags = ent->flags;
7833 rsurface.matrix = ent->matrix;
7834 rsurface.inversematrix = ent->inversematrix;
7835 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7836 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7837 R_EntityMatrix(&rsurface.matrix);
7838 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7839 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7840 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7841 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7842 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7843 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7844 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7845 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7846 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7847 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7848 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7849 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7850 rsurface.colormod[3] = ent->alpha;
7851 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7852 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7853 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7854 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7855 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7856 if (ent->model->brush.submodel && !prepass)
7858 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7859 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7861 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7863 if (ent->animcache_vertex3f)
7865 rsurface.modelvertex3f = ent->animcache_vertex3f;
7866 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7867 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7868 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7869 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7870 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7871 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7873 else if (wanttangents)
7875 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7876 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7877 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7878 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7879 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7880 rsurface.modelvertexmesh = NULL;
7881 rsurface.modelvertexmeshbuffer = NULL;
7882 rsurface.modelvertex3fbuffer = NULL;
7884 else if (wantnormals)
7886 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7887 rsurface.modelsvector3f = NULL;
7888 rsurface.modeltvector3f = NULL;
7889 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7890 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7891 rsurface.modelvertexmesh = NULL;
7892 rsurface.modelvertexmeshbuffer = NULL;
7893 rsurface.modelvertex3fbuffer = NULL;
7897 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7898 rsurface.modelsvector3f = NULL;
7899 rsurface.modeltvector3f = NULL;
7900 rsurface.modelnormal3f = NULL;
7901 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7902 rsurface.modelvertexmesh = NULL;
7903 rsurface.modelvertexmeshbuffer = NULL;
7904 rsurface.modelvertex3fbuffer = NULL;
7906 rsurface.modelvertex3f_vertexbuffer = 0;
7907 rsurface.modelvertex3f_bufferoffset = 0;
7908 rsurface.modelsvector3f_vertexbuffer = 0;
7909 rsurface.modelsvector3f_bufferoffset = 0;
7910 rsurface.modeltvector3f_vertexbuffer = 0;
7911 rsurface.modeltvector3f_bufferoffset = 0;
7912 rsurface.modelnormal3f_vertexbuffer = 0;
7913 rsurface.modelnormal3f_bufferoffset = 0;
7914 rsurface.modelgeneratedvertex = true;
7918 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7919 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7920 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7921 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7922 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7923 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7924 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7925 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7926 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7927 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7928 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7929 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7930 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7931 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7932 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7933 rsurface.modelgeneratedvertex = false;
7935 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7936 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7937 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7938 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7939 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7940 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7941 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7942 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7943 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7944 rsurface.modelelement3i = model->surfmesh.data_element3i;
7945 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7946 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7947 rsurface.modelelement3s = model->surfmesh.data_element3s;
7948 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7949 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7950 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7951 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7952 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7953 rsurface.modelsurfaces = model->data_surfaces;
7954 rsurface.batchgeneratedvertex = false;
7955 rsurface.batchfirstvertex = 0;
7956 rsurface.batchnumvertices = 0;
7957 rsurface.batchfirsttriangle = 0;
7958 rsurface.batchnumtriangles = 0;
7959 rsurface.batchvertex3f = NULL;
7960 rsurface.batchvertex3f_vertexbuffer = NULL;
7961 rsurface.batchvertex3f_bufferoffset = 0;
7962 rsurface.batchsvector3f = NULL;
7963 rsurface.batchsvector3f_vertexbuffer = NULL;
7964 rsurface.batchsvector3f_bufferoffset = 0;
7965 rsurface.batchtvector3f = NULL;
7966 rsurface.batchtvector3f_vertexbuffer = NULL;
7967 rsurface.batchtvector3f_bufferoffset = 0;
7968 rsurface.batchnormal3f = NULL;
7969 rsurface.batchnormal3f_vertexbuffer = NULL;
7970 rsurface.batchnormal3f_bufferoffset = 0;
7971 rsurface.batchlightmapcolor4f = NULL;
7972 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7973 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7974 rsurface.batchtexcoordtexture2f = NULL;
7975 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7976 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7977 rsurface.batchtexcoordlightmap2f = NULL;
7978 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7979 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7980 rsurface.batchvertexmesh = NULL;
7981 rsurface.batchvertexmeshbuffer = NULL;
7982 rsurface.batchvertex3fbuffer = NULL;
7983 rsurface.batchelement3i = NULL;
7984 rsurface.batchelement3i_indexbuffer = NULL;
7985 rsurface.batchelement3i_bufferoffset = 0;
7986 rsurface.batchelement3s = NULL;
7987 rsurface.batchelement3s_indexbuffer = NULL;
7988 rsurface.batchelement3s_bufferoffset = 0;
7989 rsurface.passcolor4f = NULL;
7990 rsurface.passcolor4f_vertexbuffer = NULL;
7991 rsurface.passcolor4f_bufferoffset = 0;
7994 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)
7996 rsurface.entity = r_refdef.scene.worldentity;
7997 rsurface.skeleton = NULL;
7998 rsurface.ent_skinnum = 0;
7999 rsurface.ent_qwskin = -1;
8000 rsurface.ent_shadertime = shadertime;
8001 rsurface.ent_flags = entflags;
8002 rsurface.modelnumvertices = numvertices;
8003 rsurface.modelnumtriangles = numtriangles;
8004 rsurface.matrix = *matrix;
8005 rsurface.inversematrix = *inversematrix;
8006 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8007 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8008 R_EntityMatrix(&rsurface.matrix);
8009 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8010 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8011 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8012 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8013 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8014 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8015 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8016 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8017 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8018 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8019 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8020 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8021 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);
8022 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8023 rsurface.frameblend[0].lerp = 1;
8024 rsurface.ent_alttextures = false;
8025 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8026 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8029 rsurface.modelvertex3f = (float *)vertex3f;
8030 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8031 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8032 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8034 else if (wantnormals)
8036 rsurface.modelvertex3f = (float *)vertex3f;
8037 rsurface.modelsvector3f = NULL;
8038 rsurface.modeltvector3f = NULL;
8039 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8043 rsurface.modelvertex3f = (float *)vertex3f;
8044 rsurface.modelsvector3f = NULL;
8045 rsurface.modeltvector3f = NULL;
8046 rsurface.modelnormal3f = NULL;
8048 rsurface.modelvertexmesh = NULL;
8049 rsurface.modelvertexmeshbuffer = NULL;
8050 rsurface.modelvertex3fbuffer = NULL;
8051 rsurface.modelvertex3f_vertexbuffer = 0;
8052 rsurface.modelvertex3f_bufferoffset = 0;
8053 rsurface.modelsvector3f_vertexbuffer = 0;
8054 rsurface.modelsvector3f_bufferoffset = 0;
8055 rsurface.modeltvector3f_vertexbuffer = 0;
8056 rsurface.modeltvector3f_bufferoffset = 0;
8057 rsurface.modelnormal3f_vertexbuffer = 0;
8058 rsurface.modelnormal3f_bufferoffset = 0;
8059 rsurface.modelgeneratedvertex = true;
8060 rsurface.modellightmapcolor4f = (float *)color4f;
8061 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8062 rsurface.modellightmapcolor4f_bufferoffset = 0;
8063 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8064 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8065 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8066 rsurface.modeltexcoordlightmap2f = NULL;
8067 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8068 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8069 rsurface.modelelement3i = (int *)element3i;
8070 rsurface.modelelement3i_indexbuffer = NULL;
8071 rsurface.modelelement3i_bufferoffset = 0;
8072 rsurface.modelelement3s = (unsigned short *)element3s;
8073 rsurface.modelelement3s_indexbuffer = NULL;
8074 rsurface.modelelement3s_bufferoffset = 0;
8075 rsurface.modellightmapoffsets = NULL;
8076 rsurface.modelsurfaces = NULL;
8077 rsurface.batchgeneratedvertex = false;
8078 rsurface.batchfirstvertex = 0;
8079 rsurface.batchnumvertices = 0;
8080 rsurface.batchfirsttriangle = 0;
8081 rsurface.batchnumtriangles = 0;
8082 rsurface.batchvertex3f = NULL;
8083 rsurface.batchvertex3f_vertexbuffer = NULL;
8084 rsurface.batchvertex3f_bufferoffset = 0;
8085 rsurface.batchsvector3f = NULL;
8086 rsurface.batchsvector3f_vertexbuffer = NULL;
8087 rsurface.batchsvector3f_bufferoffset = 0;
8088 rsurface.batchtvector3f = NULL;
8089 rsurface.batchtvector3f_vertexbuffer = NULL;
8090 rsurface.batchtvector3f_bufferoffset = 0;
8091 rsurface.batchnormal3f = NULL;
8092 rsurface.batchnormal3f_vertexbuffer = NULL;
8093 rsurface.batchnormal3f_bufferoffset = 0;
8094 rsurface.batchlightmapcolor4f = NULL;
8095 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8096 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8097 rsurface.batchtexcoordtexture2f = NULL;
8098 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8099 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8100 rsurface.batchtexcoordlightmap2f = NULL;
8101 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8102 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8103 rsurface.batchvertexmesh = NULL;
8104 rsurface.batchvertexmeshbuffer = NULL;
8105 rsurface.batchvertex3fbuffer = NULL;
8106 rsurface.batchelement3i = NULL;
8107 rsurface.batchelement3i_indexbuffer = NULL;
8108 rsurface.batchelement3i_bufferoffset = 0;
8109 rsurface.batchelement3s = NULL;
8110 rsurface.batchelement3s_indexbuffer = NULL;
8111 rsurface.batchelement3s_bufferoffset = 0;
8112 rsurface.passcolor4f = NULL;
8113 rsurface.passcolor4f_vertexbuffer = NULL;
8114 rsurface.passcolor4f_bufferoffset = 0;
8116 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8118 if ((wantnormals || wanttangents) && !normal3f)
8120 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8121 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8123 if (wanttangents && !svector3f)
8125 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8126 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8127 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8132 float RSurf_FogPoint(const float *v)
8134 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8135 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8136 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8137 float FogHeightFade = r_refdef.fogheightfade;
8139 unsigned int fogmasktableindex;
8140 if (r_refdef.fogplaneviewabove)
8141 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8143 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8144 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8145 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8148 float RSurf_FogVertex(const float *v)
8150 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8151 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8152 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8153 float FogHeightFade = rsurface.fogheightfade;
8155 unsigned int fogmasktableindex;
8156 if (r_refdef.fogplaneviewabove)
8157 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8159 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8160 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8161 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8164 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8167 for (i = 0;i < numelements;i++)
8168 outelement3i[i] = inelement3i[i] + adjust;
8171 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8172 extern cvar_t gl_vbo;
8173 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8181 int surfacefirsttriangle;
8182 int surfacenumtriangles;
8183 int surfacefirstvertex;
8184 int surfaceendvertex;
8185 int surfacenumvertices;
8186 int batchnumvertices;
8187 int batchnumtriangles;
8191 qboolean dynamicvertex;
8195 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8197 q3shaderinfo_deform_t *deform;
8198 const msurface_t *surface, *firstsurface;
8199 r_vertexmesh_t *vertexmesh;
8200 if (!texturenumsurfaces)
8202 // find vertex range of this surface batch
8204 firstsurface = texturesurfacelist[0];
8205 firsttriangle = firstsurface->num_firsttriangle;
8206 batchnumvertices = 0;
8207 batchnumtriangles = 0;
8208 firstvertex = endvertex = firstsurface->num_firstvertex;
8209 for (i = 0;i < texturenumsurfaces;i++)
8211 surface = texturesurfacelist[i];
8212 if (surface != firstsurface + i)
8214 surfacefirstvertex = surface->num_firstvertex;
8215 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8216 surfacenumvertices = surface->num_vertices;
8217 surfacenumtriangles = surface->num_triangles;
8218 if (firstvertex > surfacefirstvertex)
8219 firstvertex = surfacefirstvertex;
8220 if (endvertex < surfaceendvertex)
8221 endvertex = surfaceendvertex;
8222 batchnumvertices += surfacenumvertices;
8223 batchnumtriangles += surfacenumtriangles;
8226 // we now know the vertex range used, and if there are any gaps in it
8227 rsurface.batchfirstvertex = firstvertex;
8228 rsurface.batchnumvertices = endvertex - firstvertex;
8229 rsurface.batchfirsttriangle = firsttriangle;
8230 rsurface.batchnumtriangles = batchnumtriangles;
8232 // this variable holds flags for which properties have been updated that
8233 // may require regenerating vertexmesh array...
8236 // check if any dynamic vertex processing must occur
8237 dynamicvertex = false;
8239 // if there is a chance of animated vertex colors, it's a dynamic batch
8240 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8242 dynamicvertex = true;
8243 batchneed |= BATCHNEED_NOGAPS;
8244 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8247 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8249 switch (deform->deform)
8252 case Q3DEFORM_PROJECTIONSHADOW:
8253 case Q3DEFORM_TEXT0:
8254 case Q3DEFORM_TEXT1:
8255 case Q3DEFORM_TEXT2:
8256 case Q3DEFORM_TEXT3:
8257 case Q3DEFORM_TEXT4:
8258 case Q3DEFORM_TEXT5:
8259 case Q3DEFORM_TEXT6:
8260 case Q3DEFORM_TEXT7:
8263 case Q3DEFORM_AUTOSPRITE:
8264 dynamicvertex = true;
8265 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8266 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8268 case Q3DEFORM_AUTOSPRITE2:
8269 dynamicvertex = true;
8270 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8271 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8273 case Q3DEFORM_NORMAL:
8274 dynamicvertex = true;
8275 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8276 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8279 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8280 break; // if wavefunc is a nop, ignore this transform
8281 dynamicvertex = true;
8282 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8283 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8285 case Q3DEFORM_BULGE:
8286 dynamicvertex = true;
8287 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8288 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8291 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8292 break; // if wavefunc is a nop, ignore this transform
8293 dynamicvertex = true;
8294 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8295 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8299 switch(rsurface.texture->tcgen.tcgen)
8302 case Q3TCGEN_TEXTURE:
8304 case Q3TCGEN_LIGHTMAP:
8305 dynamicvertex = true;
8306 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8307 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8309 case Q3TCGEN_VECTOR:
8310 dynamicvertex = true;
8311 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8312 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8314 case Q3TCGEN_ENVIRONMENT:
8315 dynamicvertex = true;
8316 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8317 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8320 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8322 dynamicvertex = true;
8323 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8324 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8327 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8329 dynamicvertex = true;
8330 batchneed |= BATCHNEED_NOGAPS;
8331 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8334 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8336 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8337 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8338 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8339 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8340 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8341 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8342 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8345 // when the model data has no vertex buffer (dynamic mesh), we need to
8347 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8348 batchneed |= BATCHNEED_NOGAPS;
8350 // if needsupdate, we have to do a dynamic vertex batch for sure
8351 if (needsupdate & batchneed)
8352 dynamicvertex = true;
8354 // see if we need to build vertexmesh from arrays
8355 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8356 dynamicvertex = true;
8358 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8359 // also some drivers strongly dislike firstvertex
8360 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8361 dynamicvertex = true;
8363 rsurface.batchvertex3f = rsurface.modelvertex3f;
8364 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8365 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8366 rsurface.batchsvector3f = rsurface.modelsvector3f;
8367 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8368 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8369 rsurface.batchtvector3f = rsurface.modeltvector3f;
8370 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8371 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8372 rsurface.batchnormal3f = rsurface.modelnormal3f;
8373 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8374 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8375 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8376 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8377 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8378 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8379 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8380 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8381 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8382 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8383 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8384 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8385 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8386 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8387 rsurface.batchelement3i = rsurface.modelelement3i;
8388 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8389 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8390 rsurface.batchelement3s = rsurface.modelelement3s;
8391 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8392 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8394 // if any dynamic vertex processing has to occur in software, we copy the
8395 // entire surface list together before processing to rebase the vertices
8396 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8398 // if any gaps exist and we do not have a static vertex buffer, we have to
8399 // copy the surface list together to avoid wasting upload bandwidth on the
8400 // vertices in the gaps.
8402 // if gaps exist and we have a static vertex buffer, we still have to
8403 // combine the index buffer ranges into one dynamic index buffer.
8405 // in all cases we end up with data that can be drawn in one call.
8409 // static vertex data, just set pointers...
8410 rsurface.batchgeneratedvertex = false;
8411 // if there are gaps, we want to build a combined index buffer,
8412 // otherwise use the original static buffer with an appropriate offset
8415 // build a new triangle elements array for this batch
8416 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8417 rsurface.batchfirsttriangle = 0;
8419 for (i = 0;i < texturenumsurfaces;i++)
8421 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8422 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8423 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8424 numtriangles += surfacenumtriangles;
8426 rsurface.batchelement3i_indexbuffer = NULL;
8427 rsurface.batchelement3i_bufferoffset = 0;
8428 rsurface.batchelement3s = NULL;
8429 rsurface.batchelement3s_indexbuffer = NULL;
8430 rsurface.batchelement3s_bufferoffset = 0;
8431 if (endvertex <= 65536)
8433 // make a 16bit (unsigned short) index array if possible
8434 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8435 for (i = 0;i < numtriangles*3;i++)
8436 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8442 // something needs software processing, do it for real...
8443 // we only directly handle separate array data in this case and then
8444 // generate interleaved data if needed...
8445 rsurface.batchgeneratedvertex = true;
8447 // now copy the vertex data into a combined array and make an index array
8448 // (this is what Quake3 does all the time)
8449 //if (gaps || rsurface.batchfirstvertex)
8451 rsurface.batchvertex3fbuffer = NULL;
8452 rsurface.batchvertexmesh = NULL;
8453 rsurface.batchvertexmeshbuffer = NULL;
8454 rsurface.batchvertex3f = NULL;
8455 rsurface.batchvertex3f_vertexbuffer = NULL;
8456 rsurface.batchvertex3f_bufferoffset = 0;
8457 rsurface.batchsvector3f = NULL;
8458 rsurface.batchsvector3f_vertexbuffer = NULL;
8459 rsurface.batchsvector3f_bufferoffset = 0;
8460 rsurface.batchtvector3f = NULL;
8461 rsurface.batchtvector3f_vertexbuffer = NULL;
8462 rsurface.batchtvector3f_bufferoffset = 0;
8463 rsurface.batchnormal3f = NULL;
8464 rsurface.batchnormal3f_vertexbuffer = NULL;
8465 rsurface.batchnormal3f_bufferoffset = 0;
8466 rsurface.batchlightmapcolor4f = NULL;
8467 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8468 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8469 rsurface.batchtexcoordtexture2f = NULL;
8470 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8471 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8472 rsurface.batchtexcoordlightmap2f = NULL;
8473 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8474 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8475 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8476 rsurface.batchelement3i_indexbuffer = NULL;
8477 rsurface.batchelement3i_bufferoffset = 0;
8478 rsurface.batchelement3s = NULL;
8479 rsurface.batchelement3s_indexbuffer = NULL;
8480 rsurface.batchelement3s_bufferoffset = 0;
8481 // we'll only be setting up certain arrays as needed
8482 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8483 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8484 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8485 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8486 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8487 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8488 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8490 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8491 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8493 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8494 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8495 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8496 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8497 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8498 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8501 for (i = 0;i < texturenumsurfaces;i++)
8503 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8504 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8505 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8506 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8507 // copy only the data requested
8508 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8509 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8510 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8512 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8513 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8514 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8515 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8516 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8518 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8519 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8521 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8522 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8523 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8524 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8525 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8526 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8528 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8529 numvertices += surfacenumvertices;
8530 numtriangles += surfacenumtriangles;
8533 // generate a 16bit index array as well if possible
8534 // (in general, dynamic batches fit)
8535 if (numvertices <= 65536)
8537 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8538 for (i = 0;i < numtriangles*3;i++)
8539 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8542 // since we've copied everything, the batch now starts at 0
8543 rsurface.batchfirstvertex = 0;
8544 rsurface.batchnumvertices = batchnumvertices;
8545 rsurface.batchfirsttriangle = 0;
8546 rsurface.batchnumtriangles = batchnumtriangles;
8549 // q1bsp surfaces rendered in vertex color mode have to have colors
8550 // calculated based on lightstyles
8551 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8553 // generate color arrays for the surfaces in this list
8558 const unsigned char *lm;
8559 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8560 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8561 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8563 for (i = 0;i < texturenumsurfaces;i++)
8565 surface = texturesurfacelist[i];
8566 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8567 surfacenumvertices = surface->num_vertices;
8568 if (surface->lightmapinfo->samples)
8570 for (j = 0;j < surfacenumvertices;j++)
8572 lm = surface->lightmapinfo->samples + offsets[j];
8573 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8574 VectorScale(lm, scale, c);
8575 if (surface->lightmapinfo->styles[1] != 255)
8577 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8579 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8580 VectorMA(c, scale, lm, c);
8581 if (surface->lightmapinfo->styles[2] != 255)
8584 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8585 VectorMA(c, scale, lm, c);
8586 if (surface->lightmapinfo->styles[3] != 255)
8589 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8590 VectorMA(c, scale, lm, c);
8597 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);
8603 for (j = 0;j < surfacenumvertices;j++)
8605 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8612 // if vertices are deformed (sprite flares and things in maps, possibly
8613 // water waves, bulges and other deformations), modify the copied vertices
8615 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8617 switch (deform->deform)
8620 case Q3DEFORM_PROJECTIONSHADOW:
8621 case Q3DEFORM_TEXT0:
8622 case Q3DEFORM_TEXT1:
8623 case Q3DEFORM_TEXT2:
8624 case Q3DEFORM_TEXT3:
8625 case Q3DEFORM_TEXT4:
8626 case Q3DEFORM_TEXT5:
8627 case Q3DEFORM_TEXT6:
8628 case Q3DEFORM_TEXT7:
8631 case Q3DEFORM_AUTOSPRITE:
8632 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8633 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8634 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8635 VectorNormalize(newforward);
8636 VectorNormalize(newright);
8637 VectorNormalize(newup);
8638 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8639 // rsurface.batchvertex3f_vertexbuffer = NULL;
8640 // rsurface.batchvertex3f_bufferoffset = 0;
8641 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8642 // rsurface.batchsvector3f_vertexbuffer = NULL;
8643 // rsurface.batchsvector3f_bufferoffset = 0;
8644 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8645 // rsurface.batchtvector3f_vertexbuffer = NULL;
8646 // rsurface.batchtvector3f_bufferoffset = 0;
8647 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8648 // rsurface.batchnormal3f_vertexbuffer = NULL;
8649 // rsurface.batchnormal3f_bufferoffset = 0;
8650 // a single autosprite surface can contain multiple sprites...
8651 for (j = 0;j < batchnumvertices - 3;j += 4)
8653 VectorClear(center);
8654 for (i = 0;i < 4;i++)
8655 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8656 VectorScale(center, 0.25f, center);
8657 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8658 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8659 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8660 for (i = 0;i < 4;i++)
8662 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8663 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8666 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8667 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8668 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);
8670 case Q3DEFORM_AUTOSPRITE2:
8671 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8672 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8673 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8674 VectorNormalize(newforward);
8675 VectorNormalize(newright);
8676 VectorNormalize(newup);
8677 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8678 // rsurface.batchvertex3f_vertexbuffer = NULL;
8679 // rsurface.batchvertex3f_bufferoffset = 0;
8681 const float *v1, *v2;
8691 memset(shortest, 0, sizeof(shortest));
8692 // a single autosprite surface can contain multiple sprites...
8693 for (j = 0;j < batchnumvertices - 3;j += 4)
8695 VectorClear(center);
8696 for (i = 0;i < 4;i++)
8697 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8698 VectorScale(center, 0.25f, center);
8699 // find the two shortest edges, then use them to define the
8700 // axis vectors for rotating around the central axis
8701 for (i = 0;i < 6;i++)
8703 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8704 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8705 l = VectorDistance2(v1, v2);
8706 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8708 l += (1.0f / 1024.0f);
8709 if (shortest[0].length2 > l || i == 0)
8711 shortest[1] = shortest[0];
8712 shortest[0].length2 = l;
8713 shortest[0].v1 = v1;
8714 shortest[0].v2 = v2;
8716 else if (shortest[1].length2 > l || i == 1)
8718 shortest[1].length2 = l;
8719 shortest[1].v1 = v1;
8720 shortest[1].v2 = v2;
8723 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8724 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8725 // this calculates the right vector from the shortest edge
8726 // and the up vector from the edge midpoints
8727 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8728 VectorNormalize(right);
8729 VectorSubtract(end, start, up);
8730 VectorNormalize(up);
8731 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8732 VectorSubtract(rsurface.localvieworigin, center, forward);
8733 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8734 VectorNegate(forward, forward);
8735 VectorReflect(forward, 0, up, forward);
8736 VectorNormalize(forward);
8737 CrossProduct(up, forward, newright);
8738 VectorNormalize(newright);
8739 // rotate the quad around the up axis vector, this is made
8740 // especially easy by the fact we know the quad is flat,
8741 // so we only have to subtract the center position and
8742 // measure distance along the right vector, and then
8743 // multiply that by the newright vector and add back the
8745 // we also need to subtract the old position to undo the
8746 // displacement from the center, which we do with a
8747 // DotProduct, the subtraction/addition of center is also
8748 // optimized into DotProducts here
8749 l = DotProduct(right, center);
8750 for (i = 0;i < 4;i++)
8752 v1 = rsurface.batchvertex3f + 3*(j+i);
8753 f = DotProduct(right, v1) - l;
8754 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8758 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8760 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8761 // rsurface.batchnormal3f_vertexbuffer = NULL;
8762 // rsurface.batchnormal3f_bufferoffset = 0;
8763 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8765 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8767 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8768 // rsurface.batchsvector3f_vertexbuffer = NULL;
8769 // rsurface.batchsvector3f_bufferoffset = 0;
8770 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8771 // rsurface.batchtvector3f_vertexbuffer = NULL;
8772 // rsurface.batchtvector3f_bufferoffset = 0;
8773 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);
8776 case Q3DEFORM_NORMAL:
8777 // deform the normals to make reflections wavey
8778 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8779 rsurface.batchnormal3f_vertexbuffer = NULL;
8780 rsurface.batchnormal3f_bufferoffset = 0;
8781 for (j = 0;j < batchnumvertices;j++)
8784 float *normal = rsurface.batchnormal3f + 3*j;
8785 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8786 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8787 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]);
8788 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]);
8789 VectorNormalize(normal);
8791 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8793 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8794 // rsurface.batchsvector3f_vertexbuffer = NULL;
8795 // rsurface.batchsvector3f_bufferoffset = 0;
8796 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8797 // rsurface.batchtvector3f_vertexbuffer = NULL;
8798 // rsurface.batchtvector3f_bufferoffset = 0;
8799 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);
8803 // deform vertex array to make wavey water and flags and such
8804 waveparms[0] = deform->waveparms[0];
8805 waveparms[1] = deform->waveparms[1];
8806 waveparms[2] = deform->waveparms[2];
8807 waveparms[3] = deform->waveparms[3];
8808 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8809 break; // if wavefunc is a nop, don't make a dynamic vertex array
8810 // this is how a divisor of vertex influence on deformation
8811 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8812 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8813 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8814 // rsurface.batchvertex3f_vertexbuffer = NULL;
8815 // rsurface.batchvertex3f_bufferoffset = 0;
8816 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8817 // rsurface.batchnormal3f_vertexbuffer = NULL;
8818 // rsurface.batchnormal3f_bufferoffset = 0;
8819 for (j = 0;j < batchnumvertices;j++)
8821 // if the wavefunc depends on time, evaluate it per-vertex
8824 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8825 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8827 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8829 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8830 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8831 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8833 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8834 // rsurface.batchsvector3f_vertexbuffer = NULL;
8835 // rsurface.batchsvector3f_bufferoffset = 0;
8836 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8837 // rsurface.batchtvector3f_vertexbuffer = NULL;
8838 // rsurface.batchtvector3f_bufferoffset = 0;
8839 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);
8842 case Q3DEFORM_BULGE:
8843 // deform vertex array to make the surface have moving bulges
8844 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8845 // rsurface.batchvertex3f_vertexbuffer = NULL;
8846 // rsurface.batchvertex3f_bufferoffset = 0;
8847 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8848 // rsurface.batchnormal3f_vertexbuffer = NULL;
8849 // rsurface.batchnormal3f_bufferoffset = 0;
8850 for (j = 0;j < batchnumvertices;j++)
8852 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8853 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8855 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8856 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8857 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8859 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8860 // rsurface.batchsvector3f_vertexbuffer = NULL;
8861 // rsurface.batchsvector3f_bufferoffset = 0;
8862 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8863 // rsurface.batchtvector3f_vertexbuffer = NULL;
8864 // rsurface.batchtvector3f_bufferoffset = 0;
8865 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);
8869 // deform vertex array
8870 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8871 break; // if wavefunc is a nop, don't make a dynamic vertex array
8872 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8873 VectorScale(deform->parms, scale, waveparms);
8874 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8875 // rsurface.batchvertex3f_vertexbuffer = NULL;
8876 // rsurface.batchvertex3f_bufferoffset = 0;
8877 for (j = 0;j < batchnumvertices;j++)
8878 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8883 // generate texcoords based on the chosen texcoord source
8884 switch(rsurface.texture->tcgen.tcgen)
8887 case Q3TCGEN_TEXTURE:
8889 case Q3TCGEN_LIGHTMAP:
8890 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8891 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8892 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8893 if (rsurface.batchtexcoordlightmap2f)
8894 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8896 case Q3TCGEN_VECTOR:
8897 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8898 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8899 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8900 for (j = 0;j < batchnumvertices;j++)
8902 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8903 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8906 case Q3TCGEN_ENVIRONMENT:
8907 // make environment reflections using a spheremap
8908 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8909 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8910 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8911 for (j = 0;j < batchnumvertices;j++)
8913 // identical to Q3A's method, but executed in worldspace so
8914 // carried models can be shiny too
8916 float viewer[3], d, reflected[3], worldreflected[3];
8918 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8919 // VectorNormalize(viewer);
8921 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8923 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8924 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8925 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8926 // note: this is proportinal to viewer, so we can normalize later
8928 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8929 VectorNormalize(worldreflected);
8931 // note: this sphere map only uses world x and z!
8932 // so positive and negative y will LOOK THE SAME.
8933 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8934 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8938 // the only tcmod that needs software vertex processing is turbulent, so
8939 // check for it here and apply the changes if needed
8940 // and we only support that as the first one
8941 // (handling a mixture of turbulent and other tcmods would be problematic
8942 // without punting it entirely to a software path)
8943 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8945 amplitude = rsurface.texture->tcmods[0].parms[1];
8946 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8947 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8948 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8949 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8950 for (j = 0;j < batchnumvertices;j++)
8952 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);
8953 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8957 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8959 // convert the modified arrays to vertex structs
8960 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8961 // rsurface.batchvertexmeshbuffer = NULL;
8962 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8963 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8964 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8965 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8966 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8967 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
8968 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
8970 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8972 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
8973 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
8976 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
8977 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8978 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
8979 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
8980 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8981 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
8982 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
8983 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8984 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
8988 void RSurf_DrawBatch(void)
8990 // sometimes a zero triangle surface (usually a degenerate patch) makes it
8991 // through the pipeline, killing it earlier in the pipeline would have
8992 // per-surface overhead rather than per-batch overhead, so it's best to
8993 // reject it here, before it hits glDraw.
8994 if (rsurface.batchnumtriangles == 0)
8997 // batch debugging code
8998 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9004 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9005 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9008 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9010 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9012 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9013 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);
9020 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);
9023 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9025 // pick the closest matching water plane
9026 int planeindex, vertexindex, bestplaneindex = -1;
9030 r_waterstate_waterplane_t *p;
9031 qboolean prepared = false;
9033 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9035 if(p->camera_entity != rsurface.texture->camera_entity)
9040 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9042 if(rsurface.batchnumvertices == 0)
9045 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9047 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9048 d += fabs(PlaneDiff(vert, &p->plane));
9050 if (bestd > d || bestplaneindex < 0)
9053 bestplaneindex = planeindex;
9056 return bestplaneindex;
9057 // NOTE: this MAY return a totally unrelated water plane; we can ignore
9058 // this situation though, as it might be better to render single larger
9059 // batches with useless stuff (backface culled for example) than to
9060 // render multiple smaller batches
9063 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9066 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9067 rsurface.passcolor4f_vertexbuffer = 0;
9068 rsurface.passcolor4f_bufferoffset = 0;
9069 for (i = 0;i < rsurface.batchnumvertices;i++)
9070 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9073 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9080 if (rsurface.passcolor4f)
9082 // generate color arrays
9083 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9084 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9085 rsurface.passcolor4f_vertexbuffer = 0;
9086 rsurface.passcolor4f_bufferoffset = 0;
9087 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)
9089 f = RSurf_FogVertex(v);
9098 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9099 rsurface.passcolor4f_vertexbuffer = 0;
9100 rsurface.passcolor4f_bufferoffset = 0;
9101 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9103 f = RSurf_FogVertex(v);
9112 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9119 if (!rsurface.passcolor4f)
9121 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9122 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9123 rsurface.passcolor4f_vertexbuffer = 0;
9124 rsurface.passcolor4f_bufferoffset = 0;
9125 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)
9127 f = RSurf_FogVertex(v);
9128 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9129 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9130 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9135 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9140 if (!rsurface.passcolor4f)
9142 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9143 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9144 rsurface.passcolor4f_vertexbuffer = 0;
9145 rsurface.passcolor4f_bufferoffset = 0;
9146 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9155 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9160 if (!rsurface.passcolor4f)
9162 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9163 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9164 rsurface.passcolor4f_vertexbuffer = 0;
9165 rsurface.passcolor4f_bufferoffset = 0;
9166 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9168 c2[0] = c[0] + r_refdef.scene.ambient;
9169 c2[1] = c[1] + r_refdef.scene.ambient;
9170 c2[2] = c[2] + r_refdef.scene.ambient;
9175 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9178 rsurface.passcolor4f = NULL;
9179 rsurface.passcolor4f_vertexbuffer = 0;
9180 rsurface.passcolor4f_bufferoffset = 0;
9181 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9182 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9183 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9184 GL_Color(r, g, b, a);
9185 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9189 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9191 // TODO: optimize applyfog && applycolor case
9192 // just apply fog if necessary, and tint the fog color array if necessary
9193 rsurface.passcolor4f = NULL;
9194 rsurface.passcolor4f_vertexbuffer = 0;
9195 rsurface.passcolor4f_bufferoffset = 0;
9196 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9197 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9198 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9199 GL_Color(r, g, b, a);
9203 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9206 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9207 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9208 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9209 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9210 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9211 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9212 GL_Color(r, g, b, a);
9216 static void RSurf_DrawBatch_GL11_ClampColor(void)
9221 if (!rsurface.passcolor4f)
9223 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9225 c2[0] = bound(0.0f, c1[0], 1.0f);
9226 c2[1] = bound(0.0f, c1[1], 1.0f);
9227 c2[2] = bound(0.0f, c1[2], 1.0f);
9228 c2[3] = bound(0.0f, c1[3], 1.0f);
9232 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9242 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9243 rsurface.passcolor4f_vertexbuffer = 0;
9244 rsurface.passcolor4f_bufferoffset = 0;
9245 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)
9247 f = -DotProduct(r_refdef.view.forward, n);
9249 f = f * 0.85 + 0.15; // work around so stuff won't get black
9250 f *= r_refdef.lightmapintensity;
9251 Vector4Set(c, f, f, f, 1);
9255 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9257 RSurf_DrawBatch_GL11_ApplyFakeLight();
9258 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9259 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9260 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9261 GL_Color(r, g, b, a);
9265 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9273 vec3_t ambientcolor;
9274 vec3_t diffusecolor;
9278 VectorCopy(rsurface.modellight_lightdir, lightdir);
9279 f = 0.5f * r_refdef.lightmapintensity;
9280 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9281 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9282 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9283 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9284 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9285 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9287 if (VectorLength2(diffusecolor) > 0)
9289 // q3-style directional shading
9290 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9291 rsurface.passcolor4f_vertexbuffer = 0;
9292 rsurface.passcolor4f_bufferoffset = 0;
9293 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)
9295 if ((f = DotProduct(n, lightdir)) > 0)
9296 VectorMA(ambientcolor, f, diffusecolor, c);
9298 VectorCopy(ambientcolor, c);
9305 *applycolor = false;
9309 *r = ambientcolor[0];
9310 *g = ambientcolor[1];
9311 *b = ambientcolor[2];
9312 rsurface.passcolor4f = NULL;
9313 rsurface.passcolor4f_vertexbuffer = 0;
9314 rsurface.passcolor4f_bufferoffset = 0;
9318 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9320 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9321 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9322 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9323 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9324 GL_Color(r, g, b, a);
9328 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9336 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9337 rsurface.passcolor4f_vertexbuffer = 0;
9338 rsurface.passcolor4f_bufferoffset = 0;
9340 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9342 f = 1 - RSurf_FogVertex(v);
9350 void RSurf_SetupDepthAndCulling(void)
9352 // submodels are biased to avoid z-fighting with world surfaces that they
9353 // may be exactly overlapping (avoids z-fighting artifacts on certain
9354 // doors and things in Quake maps)
9355 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9356 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9357 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9358 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9361 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9363 // transparent sky would be ridiculous
9364 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9366 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9367 skyrenderlater = true;
9368 RSurf_SetupDepthAndCulling();
9370 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9371 // skymasking on them, and Quake3 never did sky masking (unlike
9372 // software Quake and software Quake2), so disable the sky masking
9373 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9374 // and skymasking also looks very bad when noclipping outside the
9375 // level, so don't use it then either.
9376 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9378 R_Mesh_ResetTextureState();
9379 if (skyrendermasked)
9381 R_SetupShader_DepthOrShadow();
9382 // depth-only (masking)
9383 GL_ColorMask(0,0,0,0);
9384 // just to make sure that braindead drivers don't draw
9385 // anything despite that colormask...
9386 GL_BlendFunc(GL_ZERO, GL_ONE);
9387 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9388 if (rsurface.batchvertex3fbuffer)
9389 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9391 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9395 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9397 GL_BlendFunc(GL_ONE, GL_ZERO);
9398 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9399 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9400 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9403 if (skyrendermasked)
9404 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9406 R_Mesh_ResetTextureState();
9407 GL_Color(1, 1, 1, 1);
9410 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9411 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9412 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9414 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9418 // render screenspace normalmap to texture
9420 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9425 // bind lightmap texture
9427 // water/refraction/reflection/camera surfaces have to be handled specially
9428 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9430 int start, end, startplaneindex;
9431 for (start = 0;start < texturenumsurfaces;start = end)
9433 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9434 if(startplaneindex < 0)
9436 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9437 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9441 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9443 // now that we have a batch using the same planeindex, render it
9444 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9446 // render water or distortion background
9448 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));
9450 // blend surface on top
9451 GL_DepthMask(false);
9452 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9455 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9457 // render surface with reflection texture as input
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, end-start, texturesurfacelist + start, (void *)(r_waterstate.waterplanes + startplaneindex));
9466 // render surface batch normally
9467 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9468 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9472 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9474 // OpenGL 1.3 path - anything not completely ancient
9475 qboolean applycolor;
9478 const texturelayer_t *layer;
9479 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);
9480 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9482 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9485 int layertexrgbscale;
9486 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9488 if (layerindex == 0)
9492 GL_AlphaTest(false);
9493 GL_DepthFunc(GL_EQUAL);
9496 GL_DepthMask(layer->depthmask && writedepth);
9497 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9498 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9500 layertexrgbscale = 4;
9501 VectorScale(layer->color, 0.25f, layercolor);
9503 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9505 layertexrgbscale = 2;
9506 VectorScale(layer->color, 0.5f, layercolor);
9510 layertexrgbscale = 1;
9511 VectorScale(layer->color, 1.0f, layercolor);
9513 layercolor[3] = layer->color[3];
9514 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9515 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9516 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9517 switch (layer->type)
9519 case TEXTURELAYERTYPE_LITTEXTURE:
9520 // single-pass lightmapped texture with 2x rgbscale
9521 R_Mesh_TexBind(0, r_texture_white);
9522 R_Mesh_TexMatrix(0, NULL);
9523 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9524 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9525 R_Mesh_TexBind(1, layer->texture);
9526 R_Mesh_TexMatrix(1, &layer->texmatrix);
9527 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9528 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9529 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9530 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9531 else if (FAKELIGHT_ENABLED)
9532 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9533 else if (rsurface.uselightmaptexture)
9534 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9536 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9538 case TEXTURELAYERTYPE_TEXTURE:
9539 // singletexture unlit texture with transparency support
9540 R_Mesh_TexBind(0, layer->texture);
9541 R_Mesh_TexMatrix(0, &layer->texmatrix);
9542 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9543 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9544 R_Mesh_TexBind(1, 0);
9545 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9546 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9548 case TEXTURELAYERTYPE_FOG:
9549 // singletexture fogging
9552 R_Mesh_TexBind(0, layer->texture);
9553 R_Mesh_TexMatrix(0, &layer->texmatrix);
9554 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9555 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9559 R_Mesh_TexBind(0, 0);
9560 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9562 R_Mesh_TexBind(1, 0);
9563 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9564 // generate a color array for the fog pass
9565 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9566 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9570 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9573 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9575 GL_DepthFunc(GL_LEQUAL);
9576 GL_AlphaTest(false);
9580 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9582 // OpenGL 1.1 - crusty old voodoo path
9585 const texturelayer_t *layer;
9586 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);
9587 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9589 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9591 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9593 if (layerindex == 0)
9597 GL_AlphaTest(false);
9598 GL_DepthFunc(GL_EQUAL);
9601 GL_DepthMask(layer->depthmask && writedepth);
9602 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9603 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9604 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9605 switch (layer->type)
9607 case TEXTURELAYERTYPE_LITTEXTURE:
9608 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9610 // two-pass lit texture with 2x rgbscale
9611 // first the lightmap pass
9612 R_Mesh_TexBind(0, r_texture_white);
9613 R_Mesh_TexMatrix(0, NULL);
9614 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9615 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9616 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9617 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9618 else if (FAKELIGHT_ENABLED)
9619 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9620 else if (rsurface.uselightmaptexture)
9621 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9623 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9624 // then apply the texture to it
9625 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
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 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);
9634 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9635 R_Mesh_TexBind(0, layer->texture);
9636 R_Mesh_TexMatrix(0, &layer->texmatrix);
9637 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9638 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9639 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9640 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);
9642 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);
9645 case TEXTURELAYERTYPE_TEXTURE:
9646 // singletexture unlit texture with transparency support
9647 R_Mesh_TexBind(0, layer->texture);
9648 R_Mesh_TexMatrix(0, &layer->texmatrix);
9649 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9650 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9651 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);
9653 case TEXTURELAYERTYPE_FOG:
9654 // singletexture fogging
9657 R_Mesh_TexBind(0, layer->texture);
9658 R_Mesh_TexMatrix(0, &layer->texmatrix);
9659 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9660 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9664 R_Mesh_TexBind(0, 0);
9665 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9667 // generate a color array for the fog pass
9668 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9669 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9673 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9676 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9678 GL_DepthFunc(GL_LEQUAL);
9679 GL_AlphaTest(false);
9683 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9687 r_vertexgeneric_t *batchvertex;
9690 // R_Mesh_ResetTextureState();
9691 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9693 if(rsurface.texture && rsurface.texture->currentskinframe)
9695 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9696 c[3] *= rsurface.texture->currentalpha;
9706 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9708 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9709 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9710 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9713 // brighten it up (as texture value 127 means "unlit")
9714 c[0] *= 2 * r_refdef.view.colorscale;
9715 c[1] *= 2 * r_refdef.view.colorscale;
9716 c[2] *= 2 * r_refdef.view.colorscale;
9718 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9719 c[3] *= r_wateralpha.value;
9721 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9723 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9724 GL_DepthMask(false);
9726 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9728 GL_BlendFunc(GL_ONE, GL_ONE);
9729 GL_DepthMask(false);
9731 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9733 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9734 GL_DepthMask(false);
9736 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9738 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9739 GL_DepthMask(false);
9743 GL_BlendFunc(GL_ONE, GL_ZERO);
9744 GL_DepthMask(writedepth);
9747 if (r_showsurfaces.integer == 3)
9749 rsurface.passcolor4f = NULL;
9751 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9753 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9755 rsurface.passcolor4f = NULL;
9756 rsurface.passcolor4f_vertexbuffer = 0;
9757 rsurface.passcolor4f_bufferoffset = 0;
9759 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9761 qboolean applycolor = true;
9764 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9766 r_refdef.lightmapintensity = 1;
9767 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9768 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9770 else if (FAKELIGHT_ENABLED)
9772 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9774 r_refdef.lightmapintensity = r_fakelight_intensity.value;
9775 RSurf_DrawBatch_GL11_ApplyFakeLight();
9776 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9780 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9782 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9783 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9784 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9787 if(!rsurface.passcolor4f)
9788 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9790 RSurf_DrawBatch_GL11_ApplyAmbient();
9791 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9792 if(r_refdef.fogenabled)
9793 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9794 RSurf_DrawBatch_GL11_ClampColor();
9796 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9797 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9800 else if (!r_refdef.view.showdebug)
9802 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9803 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9804 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9806 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9807 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9809 R_Mesh_PrepareVertices_Generic_Unlock();
9812 else if (r_showsurfaces.integer == 4)
9814 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9815 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9816 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9818 unsigned char c = (vi << 3) * (1.0f / 256.0f);
9819 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9820 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9822 R_Mesh_PrepareVertices_Generic_Unlock();
9825 else if (r_showsurfaces.integer == 2)
9828 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9829 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9830 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9832 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9833 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9834 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9835 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9836 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9837 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9838 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9840 R_Mesh_PrepareVertices_Generic_Unlock();
9841 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9845 int texturesurfaceindex;
9847 const msurface_t *surface;
9848 float surfacecolor4f[4];
9849 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9850 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9852 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9854 surface = texturesurfacelist[texturesurfaceindex];
9855 k = (int)(((size_t)surface) / sizeof(msurface_t));
9856 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9857 for (j = 0;j < surface->num_vertices;j++)
9859 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9860 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9864 R_Mesh_PrepareVertices_Generic_Unlock();
9869 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9872 RSurf_SetupDepthAndCulling();
9873 if (r_showsurfaces.integer)
9875 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9878 switch (vid.renderpath)
9880 case RENDERPATH_GL20:
9881 case RENDERPATH_D3D9:
9882 case RENDERPATH_D3D10:
9883 case RENDERPATH_D3D11:
9884 case RENDERPATH_SOFT:
9885 case RENDERPATH_GLES2:
9886 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9888 case RENDERPATH_GL13:
9889 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9891 case RENDERPATH_GL11:
9892 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9898 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9901 RSurf_SetupDepthAndCulling();
9902 if (r_showsurfaces.integer)
9904 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9907 switch (vid.renderpath)
9909 case RENDERPATH_GL20:
9910 case RENDERPATH_D3D9:
9911 case RENDERPATH_D3D10:
9912 case RENDERPATH_D3D11:
9913 case RENDERPATH_SOFT:
9914 case RENDERPATH_GLES2:
9915 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9917 case RENDERPATH_GL13:
9918 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9920 case RENDERPATH_GL11:
9921 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9927 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9930 int texturenumsurfaces, endsurface;
9932 const msurface_t *surface;
9933 #define MAXBATCH_TRANSPARENTSURFACES 256
9934 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9936 // if the model is static it doesn't matter what value we give for
9937 // wantnormals and wanttangents, so this logic uses only rules applicable
9938 // to a model, knowing that they are meaningless otherwise
9939 if (ent == r_refdef.scene.worldentity)
9940 RSurf_ActiveWorldEntity();
9941 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9942 RSurf_ActiveModelEntity(ent, false, false, false);
9945 switch (vid.renderpath)
9947 case RENDERPATH_GL20:
9948 case RENDERPATH_D3D9:
9949 case RENDERPATH_D3D10:
9950 case RENDERPATH_D3D11:
9951 case RENDERPATH_SOFT:
9952 case RENDERPATH_GLES2:
9953 RSurf_ActiveModelEntity(ent, true, true, false);
9955 case RENDERPATH_GL13:
9956 case RENDERPATH_GL11:
9957 RSurf_ActiveModelEntity(ent, true, false, false);
9962 if (r_transparentdepthmasking.integer)
9964 qboolean setup = false;
9965 for (i = 0;i < numsurfaces;i = j)
9968 surface = rsurface.modelsurfaces + surfacelist[i];
9969 texture = surface->texture;
9970 rsurface.texture = R_GetCurrentTexture(texture);
9971 rsurface.lightmaptexture = NULL;
9972 rsurface.deluxemaptexture = NULL;
9973 rsurface.uselightmaptexture = false;
9974 // scan ahead until we find a different texture
9975 endsurface = min(i + 1024, numsurfaces);
9976 texturenumsurfaces = 0;
9977 texturesurfacelist[texturenumsurfaces++] = surface;
9978 for (;j < endsurface;j++)
9980 surface = rsurface.modelsurfaces + surfacelist[j];
9981 if (texture != surface->texture)
9983 texturesurfacelist[texturenumsurfaces++] = surface;
9985 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9987 // render the range of surfaces as depth
9991 GL_ColorMask(0,0,0,0);
9994 GL_BlendFunc(GL_ONE, GL_ZERO);
9996 // R_Mesh_ResetTextureState();
9997 R_SetupShader_DepthOrShadow();
9999 RSurf_SetupDepthAndCulling();
10000 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10001 if (rsurface.batchvertex3fbuffer)
10002 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10004 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10008 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10011 for (i = 0;i < numsurfaces;i = j)
10014 surface = rsurface.modelsurfaces + surfacelist[i];
10015 texture = surface->texture;
10016 rsurface.texture = R_GetCurrentTexture(texture);
10017 // scan ahead until we find a different texture
10018 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
10019 texturenumsurfaces = 0;
10020 texturesurfacelist[texturenumsurfaces++] = surface;
10021 if(FAKELIGHT_ENABLED)
10023 rsurface.lightmaptexture = NULL;
10024 rsurface.deluxemaptexture = NULL;
10025 rsurface.uselightmaptexture = false;
10026 for (;j < endsurface;j++)
10028 surface = rsurface.modelsurfaces + surfacelist[j];
10029 if (texture != surface->texture)
10031 texturesurfacelist[texturenumsurfaces++] = surface;
10036 rsurface.lightmaptexture = surface->lightmaptexture;
10037 rsurface.deluxemaptexture = surface->deluxemaptexture;
10038 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10039 for (;j < endsurface;j++)
10041 surface = rsurface.modelsurfaces + surfacelist[j];
10042 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10044 texturesurfacelist[texturenumsurfaces++] = surface;
10047 // render the range of surfaces
10048 if (ent == r_refdef.scene.worldentity)
10049 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10051 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10053 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10056 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10058 // transparent surfaces get pushed off into the transparent queue
10059 int surfacelistindex;
10060 const msurface_t *surface;
10061 vec3_t tempcenter, center;
10062 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10064 surface = texturesurfacelist[surfacelistindex];
10065 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10066 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10067 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10068 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10069 if (queueentity->transparent_offset) // transparent offset
10071 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10072 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10073 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10075 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10079 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10081 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10083 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10085 RSurf_SetupDepthAndCulling();
10086 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10087 if (rsurface.batchvertex3fbuffer)
10088 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10090 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10094 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10096 const entity_render_t *queueentity = r_refdef.scene.worldentity;
10099 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10102 if (!rsurface.texture->currentnumlayers)
10104 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10105 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10107 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10109 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10110 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10111 else if (!rsurface.texture->currentnumlayers)
10113 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10115 // in the deferred case, transparent surfaces were queued during prepass
10116 if (!r_shadow_usingdeferredprepass)
10117 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10121 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10122 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10127 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10130 texture_t *texture;
10131 R_FrameData_SetMark();
10132 // break the surface list down into batches by texture and use of lightmapping
10133 for (i = 0;i < numsurfaces;i = j)
10136 // texture is the base texture pointer, rsurface.texture is the
10137 // current frame/skin the texture is directing us to use (for example
10138 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10139 // use skin 1 instead)
10140 texture = surfacelist[i]->texture;
10141 rsurface.texture = R_GetCurrentTexture(texture);
10142 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10144 // if this texture is not the kind we want, skip ahead to the next one
10145 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10149 if(FAKELIGHT_ENABLED || depthonly || prepass)
10151 rsurface.lightmaptexture = NULL;
10152 rsurface.deluxemaptexture = NULL;
10153 rsurface.uselightmaptexture = false;
10154 // simply scan ahead until we find a different texture or lightmap state
10155 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10160 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10161 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10162 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10163 // simply scan ahead until we find a different texture or lightmap state
10164 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10167 // render the range of surfaces
10168 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10170 R_FrameData_ReturnToMark();
10173 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10177 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10180 if (!rsurface.texture->currentnumlayers)
10182 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10183 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10185 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10187 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10188 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10189 else if (!rsurface.texture->currentnumlayers)
10191 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10193 // in the deferred case, transparent surfaces were queued during prepass
10194 if (!r_shadow_usingdeferredprepass)
10195 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10199 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10200 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10205 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10208 texture_t *texture;
10209 R_FrameData_SetMark();
10210 // break the surface list down into batches by texture and use of lightmapping
10211 for (i = 0;i < numsurfaces;i = j)
10214 // texture is the base texture pointer, rsurface.texture is the
10215 // current frame/skin the texture is directing us to use (for example
10216 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10217 // use skin 1 instead)
10218 texture = surfacelist[i]->texture;
10219 rsurface.texture = R_GetCurrentTexture(texture);
10220 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10222 // if this texture is not the kind we want, skip ahead to the next one
10223 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10227 if(FAKELIGHT_ENABLED || depthonly || prepass)
10229 rsurface.lightmaptexture = NULL;
10230 rsurface.deluxemaptexture = NULL;
10231 rsurface.uselightmaptexture = false;
10232 // simply scan ahead until we find a different texture or lightmap state
10233 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10238 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10239 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10240 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10241 // simply scan ahead until we find a different texture or lightmap state
10242 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10245 // render the range of surfaces
10246 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10248 R_FrameData_ReturnToMark();
10251 float locboxvertex3f[6*4*3] =
10253 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10254 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10255 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10256 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10257 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10258 1,0,0, 0,0,0, 0,1,0, 1,1,0
10261 unsigned short locboxelements[6*2*3] =
10266 12,13,14, 12,14,15,
10267 16,17,18, 16,18,19,
10271 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10274 cl_locnode_t *loc = (cl_locnode_t *)ent;
10276 float vertex3f[6*4*3];
10278 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10279 GL_DepthMask(false);
10280 GL_DepthRange(0, 1);
10281 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10282 GL_DepthTest(true);
10283 GL_CullFace(GL_NONE);
10284 R_EntityMatrix(&identitymatrix);
10286 // R_Mesh_ResetTextureState();
10288 i = surfacelist[0];
10289 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10290 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10291 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10292 surfacelist[0] < 0 ? 0.5f : 0.125f);
10294 if (VectorCompare(loc->mins, loc->maxs))
10296 VectorSet(size, 2, 2, 2);
10297 VectorMA(loc->mins, -0.5f, size, mins);
10301 VectorCopy(loc->mins, mins);
10302 VectorSubtract(loc->maxs, loc->mins, size);
10305 for (i = 0;i < 6*4*3;)
10306 for (j = 0;j < 3;j++, i++)
10307 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10309 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10310 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10311 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10314 void R_DrawLocs(void)
10317 cl_locnode_t *loc, *nearestloc;
10319 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10320 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10322 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10323 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10327 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10329 if (decalsystem->decals)
10330 Mem_Free(decalsystem->decals);
10331 memset(decalsystem, 0, sizeof(*decalsystem));
10334 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)
10337 tridecal_t *decals;
10340 // expand or initialize the system
10341 if (decalsystem->maxdecals <= decalsystem->numdecals)
10343 decalsystem_t old = *decalsystem;
10344 qboolean useshortelements;
10345 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10346 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10347 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)));
10348 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10349 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10350 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10351 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10352 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10353 if (decalsystem->numdecals)
10354 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10356 Mem_Free(old.decals);
10357 for (i = 0;i < decalsystem->maxdecals*3;i++)
10358 decalsystem->element3i[i] = i;
10359 if (useshortelements)
10360 for (i = 0;i < decalsystem->maxdecals*3;i++)
10361 decalsystem->element3s[i] = i;
10364 // grab a decal and search for another free slot for the next one
10365 decals = decalsystem->decals;
10366 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10367 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10369 decalsystem->freedecal = i;
10370 if (decalsystem->numdecals <= i)
10371 decalsystem->numdecals = i + 1;
10373 // initialize the decal
10375 decal->triangleindex = triangleindex;
10376 decal->surfaceindex = surfaceindex;
10377 decal->decalsequence = decalsequence;
10378 decal->color4f[0][0] = c0[0];
10379 decal->color4f[0][1] = c0[1];
10380 decal->color4f[0][2] = c0[2];
10381 decal->color4f[0][3] = 1;
10382 decal->color4f[1][0] = c1[0];
10383 decal->color4f[1][1] = c1[1];
10384 decal->color4f[1][2] = c1[2];
10385 decal->color4f[1][3] = 1;
10386 decal->color4f[2][0] = c2[0];
10387 decal->color4f[2][1] = c2[1];
10388 decal->color4f[2][2] = c2[2];
10389 decal->color4f[2][3] = 1;
10390 decal->vertex3f[0][0] = v0[0];
10391 decal->vertex3f[0][1] = v0[1];
10392 decal->vertex3f[0][2] = v0[2];
10393 decal->vertex3f[1][0] = v1[0];
10394 decal->vertex3f[1][1] = v1[1];
10395 decal->vertex3f[1][2] = v1[2];
10396 decal->vertex3f[2][0] = v2[0];
10397 decal->vertex3f[2][1] = v2[1];
10398 decal->vertex3f[2][2] = v2[2];
10399 decal->texcoord2f[0][0] = t0[0];
10400 decal->texcoord2f[0][1] = t0[1];
10401 decal->texcoord2f[1][0] = t1[0];
10402 decal->texcoord2f[1][1] = t1[1];
10403 decal->texcoord2f[2][0] = t2[0];
10404 decal->texcoord2f[2][1] = t2[1];
10407 extern cvar_t cl_decals_bias;
10408 extern cvar_t cl_decals_models;
10409 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10410 // baseparms, parms, temps
10411 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)
10416 const float *vertex3f;
10417 const float *normal3f;
10419 float points[2][9][3];
10426 e = rsurface.modelelement3i + 3*triangleindex;
10428 vertex3f = rsurface.modelvertex3f;
10429 normal3f = rsurface.modelnormal3f;
10433 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10435 index = 3*e[cornerindex];
10436 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10441 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10443 index = 3*e[cornerindex];
10444 VectorCopy(vertex3f + index, v[cornerindex]);
10449 //TriangleNormal(v[0], v[1], v[2], normal);
10450 //if (DotProduct(normal, localnormal) < 0.0f)
10452 // clip by each of the box planes formed from the projection matrix
10453 // if anything survives, we emit the decal
10454 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]);
10457 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]);
10460 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]);
10463 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]);
10466 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]);
10469 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]);
10472 // some part of the triangle survived, so we have to accept it...
10475 // dynamic always uses the original triangle
10477 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10479 index = 3*e[cornerindex];
10480 VectorCopy(vertex3f + index, v[cornerindex]);
10483 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10485 // convert vertex positions to texcoords
10486 Matrix4x4_Transform(projection, v[cornerindex], temp);
10487 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10488 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10489 // calculate distance fade from the projection origin
10490 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10491 f = bound(0.0f, f, 1.0f);
10492 c[cornerindex][0] = r * f;
10493 c[cornerindex][1] = g * f;
10494 c[cornerindex][2] = b * f;
10495 c[cornerindex][3] = 1.0f;
10496 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10499 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);
10501 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10502 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);
10504 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)
10506 matrix4x4_t projection;
10507 decalsystem_t *decalsystem;
10510 const msurface_t *surface;
10511 const msurface_t *surfaces;
10512 const int *surfacelist;
10513 const texture_t *texture;
10515 int numsurfacelist;
10516 int surfacelistindex;
10519 float localorigin[3];
10520 float localnormal[3];
10521 float localmins[3];
10522 float localmaxs[3];
10525 float planes[6][4];
10528 int bih_triangles_count;
10529 int bih_triangles[256];
10530 int bih_surfaces[256];
10532 decalsystem = &ent->decalsystem;
10533 model = ent->model;
10534 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10536 R_DecalSystem_Reset(&ent->decalsystem);
10540 if (!model->brush.data_leafs && !cl_decals_models.integer)
10542 if (decalsystem->model)
10543 R_DecalSystem_Reset(decalsystem);
10547 if (decalsystem->model != model)
10548 R_DecalSystem_Reset(decalsystem);
10549 decalsystem->model = model;
10551 RSurf_ActiveModelEntity(ent, true, false, false);
10553 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10554 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10555 VectorNormalize(localnormal);
10556 localsize = worldsize*rsurface.inversematrixscale;
10557 localmins[0] = localorigin[0] - localsize;
10558 localmins[1] = localorigin[1] - localsize;
10559 localmins[2] = localorigin[2] - localsize;
10560 localmaxs[0] = localorigin[0] + localsize;
10561 localmaxs[1] = localorigin[1] + localsize;
10562 localmaxs[2] = localorigin[2] + localsize;
10564 //VectorCopy(localnormal, planes[4]);
10565 //VectorVectors(planes[4], planes[2], planes[0]);
10566 AnglesFromVectors(angles, localnormal, NULL, false);
10567 AngleVectors(angles, planes[0], planes[2], planes[4]);
10568 VectorNegate(planes[0], planes[1]);
10569 VectorNegate(planes[2], planes[3]);
10570 VectorNegate(planes[4], planes[5]);
10571 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10572 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10573 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10574 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10575 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10576 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10581 matrix4x4_t forwardprojection;
10582 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10583 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10588 float projectionvector[4][3];
10589 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10590 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10591 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10592 projectionvector[0][0] = planes[0][0] * ilocalsize;
10593 projectionvector[0][1] = planes[1][0] * ilocalsize;
10594 projectionvector[0][2] = planes[2][0] * ilocalsize;
10595 projectionvector[1][0] = planes[0][1] * ilocalsize;
10596 projectionvector[1][1] = planes[1][1] * ilocalsize;
10597 projectionvector[1][2] = planes[2][1] * ilocalsize;
10598 projectionvector[2][0] = planes[0][2] * ilocalsize;
10599 projectionvector[2][1] = planes[1][2] * ilocalsize;
10600 projectionvector[2][2] = planes[2][2] * ilocalsize;
10601 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10602 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10603 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10604 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10608 dynamic = model->surfmesh.isanimated;
10609 numsurfacelist = model->nummodelsurfaces;
10610 surfacelist = model->sortedmodelsurfaces;
10611 surfaces = model->data_surfaces;
10614 bih_triangles_count = -1;
10617 if(model->render_bih.numleafs)
10618 bih = &model->render_bih;
10619 else if(model->collision_bih.numleafs)
10620 bih = &model->collision_bih;
10623 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10624 if(bih_triangles_count == 0)
10626 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10628 if(bih_triangles_count > 0)
10630 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10632 surfaceindex = bih_surfaces[triangleindex];
10633 surface = surfaces + surfaceindex;
10634 texture = surface->texture;
10635 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10637 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10639 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10644 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10646 surfaceindex = surfacelist[surfacelistindex];
10647 surface = surfaces + surfaceindex;
10648 // check cull box first because it rejects more than any other check
10649 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10651 // skip transparent surfaces
10652 texture = surface->texture;
10653 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10655 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10657 numtriangles = surface->num_triangles;
10658 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10659 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10664 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10665 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)
10667 int renderentityindex;
10668 float worldmins[3];
10669 float worldmaxs[3];
10670 entity_render_t *ent;
10672 if (!cl_decals_newsystem.integer)
10675 worldmins[0] = worldorigin[0] - worldsize;
10676 worldmins[1] = worldorigin[1] - worldsize;
10677 worldmins[2] = worldorigin[2] - worldsize;
10678 worldmaxs[0] = worldorigin[0] + worldsize;
10679 worldmaxs[1] = worldorigin[1] + worldsize;
10680 worldmaxs[2] = worldorigin[2] + worldsize;
10682 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10684 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10686 ent = r_refdef.scene.entities[renderentityindex];
10687 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10690 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10694 typedef struct r_decalsystem_splatqueue_s
10696 vec3_t worldorigin;
10697 vec3_t worldnormal;
10703 r_decalsystem_splatqueue_t;
10705 int r_decalsystem_numqueued = 0;
10706 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10708 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)
10710 r_decalsystem_splatqueue_t *queue;
10712 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10715 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10716 VectorCopy(worldorigin, queue->worldorigin);
10717 VectorCopy(worldnormal, queue->worldnormal);
10718 Vector4Set(queue->color, r, g, b, a);
10719 Vector4Set(queue->tcrange, s1, t1, s2, t2);
10720 queue->worldsize = worldsize;
10721 queue->decalsequence = cl.decalsequence++;
10724 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10727 r_decalsystem_splatqueue_t *queue;
10729 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10730 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);
10731 r_decalsystem_numqueued = 0;
10734 extern cvar_t cl_decals_max;
10735 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10738 decalsystem_t *decalsystem = &ent->decalsystem;
10745 if (!decalsystem->numdecals)
10748 if (r_showsurfaces.integer)
10751 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10753 R_DecalSystem_Reset(decalsystem);
10757 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10758 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10760 if (decalsystem->lastupdatetime)
10761 frametime = (cl.time - decalsystem->lastupdatetime);
10764 decalsystem->lastupdatetime = cl.time;
10765 decal = decalsystem->decals;
10766 numdecals = decalsystem->numdecals;
10768 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10770 if (decal->color4f[0][3])
10772 decal->lived += frametime;
10773 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10775 memset(decal, 0, sizeof(*decal));
10776 if (decalsystem->freedecal > i)
10777 decalsystem->freedecal = i;
10781 decal = decalsystem->decals;
10782 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10785 // collapse the array by shuffling the tail decals into the gaps
10788 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10789 decalsystem->freedecal++;
10790 if (decalsystem->freedecal == numdecals)
10792 decal[decalsystem->freedecal] = decal[--numdecals];
10795 decalsystem->numdecals = numdecals;
10797 if (numdecals <= 0)
10799 // if there are no decals left, reset decalsystem
10800 R_DecalSystem_Reset(decalsystem);
10804 extern skinframe_t *decalskinframe;
10805 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10808 decalsystem_t *decalsystem = &ent->decalsystem;
10817 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10820 numdecals = decalsystem->numdecals;
10824 if (r_showsurfaces.integer)
10827 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10829 R_DecalSystem_Reset(decalsystem);
10833 // if the model is static it doesn't matter what value we give for
10834 // wantnormals and wanttangents, so this logic uses only rules applicable
10835 // to a model, knowing that they are meaningless otherwise
10836 if (ent == r_refdef.scene.worldentity)
10837 RSurf_ActiveWorldEntity();
10839 RSurf_ActiveModelEntity(ent, false, false, false);
10841 decalsystem->lastupdatetime = cl.time;
10842 decal = decalsystem->decals;
10844 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10846 // update vertex positions for animated models
10847 v3f = decalsystem->vertex3f;
10848 c4f = decalsystem->color4f;
10849 t2f = decalsystem->texcoord2f;
10850 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10852 if (!decal->color4f[0][3])
10855 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10858 // update color values for fading decals
10859 if (decal->lived >= cl_decals_time.value)
10860 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10864 c4f[ 0] = decal->color4f[0][0] * alpha;
10865 c4f[ 1] = decal->color4f[0][1] * alpha;
10866 c4f[ 2] = decal->color4f[0][2] * alpha;
10868 c4f[ 4] = decal->color4f[1][0] * alpha;
10869 c4f[ 5] = decal->color4f[1][1] * alpha;
10870 c4f[ 6] = decal->color4f[1][2] * alpha;
10872 c4f[ 8] = decal->color4f[2][0] * alpha;
10873 c4f[ 9] = decal->color4f[2][1] * alpha;
10874 c4f[10] = decal->color4f[2][2] * alpha;
10877 t2f[0] = decal->texcoord2f[0][0];
10878 t2f[1] = decal->texcoord2f[0][1];
10879 t2f[2] = decal->texcoord2f[1][0];
10880 t2f[3] = decal->texcoord2f[1][1];
10881 t2f[4] = decal->texcoord2f[2][0];
10882 t2f[5] = decal->texcoord2f[2][1];
10884 // update vertex positions for animated models
10885 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10887 e = rsurface.modelelement3i + 3*decal->triangleindex;
10888 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10889 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10890 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10894 VectorCopy(decal->vertex3f[0], v3f);
10895 VectorCopy(decal->vertex3f[1], v3f + 3);
10896 VectorCopy(decal->vertex3f[2], v3f + 6);
10899 if (r_refdef.fogenabled)
10901 alpha = RSurf_FogVertex(v3f);
10902 VectorScale(c4f, alpha, c4f);
10903 alpha = RSurf_FogVertex(v3f + 3);
10904 VectorScale(c4f + 4, alpha, c4f + 4);
10905 alpha = RSurf_FogVertex(v3f + 6);
10906 VectorScale(c4f + 8, alpha, c4f + 8);
10917 r_refdef.stats.drawndecals += numtris;
10919 // now render the decals all at once
10920 // (this assumes they all use one particle font texture!)
10921 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);
10922 // R_Mesh_ResetTextureState();
10923 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10924 GL_DepthMask(false);
10925 GL_DepthRange(0, 1);
10926 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10927 GL_DepthTest(true);
10928 GL_CullFace(GL_NONE);
10929 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10930 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10931 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10935 static void R_DrawModelDecals(void)
10939 // fade faster when there are too many decals
10940 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10941 for (i = 0;i < r_refdef.scene.numentities;i++)
10942 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10944 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10945 for (i = 0;i < r_refdef.scene.numentities;i++)
10946 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10947 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10949 R_DecalSystem_ApplySplatEntitiesQueue();
10951 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10952 for (i = 0;i < r_refdef.scene.numentities;i++)
10953 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10955 r_refdef.stats.totaldecals += numdecals;
10957 if (r_showsurfaces.integer)
10960 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10962 for (i = 0;i < r_refdef.scene.numentities;i++)
10964 if (!r_refdef.viewcache.entityvisible[i])
10966 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10967 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10971 extern cvar_t mod_collision_bih;
10972 void R_DrawDebugModel(void)
10974 entity_render_t *ent = rsurface.entity;
10975 int i, j, k, l, flagsmask;
10976 const msurface_t *surface;
10977 dp_model_t *model = ent->model;
10980 switch(vid.renderpath)
10982 case RENDERPATH_GL11:
10983 case RENDERPATH_GL13:
10984 case RENDERPATH_GL20:
10986 case RENDERPATH_D3D9:
10987 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10989 case RENDERPATH_D3D10:
10990 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10992 case RENDERPATH_D3D11:
10993 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10995 case RENDERPATH_SOFT:
10996 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10998 case RENDERPATH_GLES2:
10999 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
11003 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11005 // R_Mesh_ResetTextureState();
11006 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11007 GL_DepthRange(0, 1);
11008 GL_DepthTest(!r_showdisabledepthtest.integer);
11009 GL_DepthMask(false);
11010 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11012 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11016 qboolean cullbox = ent == r_refdef.scene.worldentity;
11017 const q3mbrush_t *brush;
11018 const bih_t *bih = &model->collision_bih;
11019 const bih_leaf_t *bihleaf;
11020 float vertex3f[3][3];
11021 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11023 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11025 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11027 switch (bihleaf->type)
11030 brush = model->brush.data_brushes + bihleaf->itemindex;
11031 if (brush->colbrushf && brush->colbrushf->numtriangles)
11033 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);
11034 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11035 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11038 case BIH_COLLISIONTRIANGLE:
11039 triangleindex = bihleaf->itemindex;
11040 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11041 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11042 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[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);
11047 case BIH_RENDERTRIANGLE:
11048 triangleindex = bihleaf->itemindex;
11049 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11050 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11051 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11052 GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
11053 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11054 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11060 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11062 if (r_showtris.integer || (r_shownormals.value != 0))
11064 if (r_showdisabledepthtest.integer)
11066 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11067 GL_DepthMask(false);
11071 GL_BlendFunc(GL_ONE, GL_ZERO);
11072 GL_DepthMask(true);
11074 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11076 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11078 rsurface.texture = R_GetCurrentTexture(surface->texture);
11079 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11081 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11082 if (r_showtris.value > 0)
11084 if (!rsurface.texture->currentlayers->depthmask)
11085 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11086 else if (ent == r_refdef.scene.worldentity)
11087 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11089 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11090 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11091 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
11093 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
11096 if (r_shownormals.value < 0)
11098 qglBegin(GL_LINES);
11099 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11101 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11102 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11103 qglVertex3f(v[0], v[1], v[2]);
11104 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11105 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11106 qglVertex3f(v[0], v[1], v[2]);
11111 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11113 qglBegin(GL_LINES);
11114 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11116 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11117 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11118 qglVertex3f(v[0], v[1], v[2]);
11119 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11120 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11121 qglVertex3f(v[0], v[1], v[2]);
11125 qglBegin(GL_LINES);
11126 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11128 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11129 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11130 qglVertex3f(v[0], v[1], v[2]);
11131 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11132 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11133 qglVertex3f(v[0], v[1], v[2]);
11137 qglBegin(GL_LINES);
11138 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11140 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11141 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11142 qglVertex3f(v[0], v[1], v[2]);
11143 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11144 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11145 qglVertex3f(v[0], v[1], v[2]);
11152 rsurface.texture = NULL;
11156 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11157 int r_maxsurfacelist = 0;
11158 const msurface_t **r_surfacelist = NULL;
11159 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11161 int i, j, endj, flagsmask;
11162 dp_model_t *model = r_refdef.scene.worldmodel;
11163 msurface_t *surfaces;
11164 unsigned char *update;
11165 int numsurfacelist = 0;
11169 if (r_maxsurfacelist < model->num_surfaces)
11171 r_maxsurfacelist = model->num_surfaces;
11173 Mem_Free((msurface_t**)r_surfacelist);
11174 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11177 RSurf_ActiveWorldEntity();
11179 surfaces = model->data_surfaces;
11180 update = model->brushq1.lightmapupdateflags;
11182 // update light styles on this submodel
11183 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11185 model_brush_lightstyleinfo_t *style;
11186 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11188 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11190 int *list = style->surfacelist;
11191 style->value = r_refdef.scene.lightstylevalue[style->style];
11192 for (j = 0;j < style->numsurfaces;j++)
11193 update[list[j]] = true;
11198 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11202 R_DrawDebugModel();
11203 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11207 rsurface.lightmaptexture = NULL;
11208 rsurface.deluxemaptexture = NULL;
11209 rsurface.uselightmaptexture = false;
11210 rsurface.texture = NULL;
11211 rsurface.rtlight = NULL;
11212 numsurfacelist = 0;
11213 // add visible surfaces to draw list
11214 for (i = 0;i < model->nummodelsurfaces;i++)
11216 j = model->sortedmodelsurfaces[i];
11217 if (r_refdef.viewcache.world_surfacevisible[j])
11218 r_surfacelist[numsurfacelist++] = surfaces + j;
11220 // update lightmaps if needed
11221 if (model->brushq1.firstrender)
11223 model->brushq1.firstrender = false;
11224 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11226 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11230 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11231 if (r_refdef.viewcache.world_surfacevisible[j])
11233 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11235 // don't do anything if there were no surfaces
11236 if (!numsurfacelist)
11238 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11241 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11243 // add to stats if desired
11244 if (r_speeds.integer && !skysurfaces && !depthonly)
11246 r_refdef.stats.world_surfaces += numsurfacelist;
11247 for (j = 0;j < numsurfacelist;j++)
11248 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11251 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11254 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11256 int i, j, endj, flagsmask;
11257 dp_model_t *model = ent->model;
11258 msurface_t *surfaces;
11259 unsigned char *update;
11260 int numsurfacelist = 0;
11264 if (r_maxsurfacelist < model->num_surfaces)
11266 r_maxsurfacelist = model->num_surfaces;
11268 Mem_Free((msurface_t **)r_surfacelist);
11269 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11272 // if the model is static it doesn't matter what value we give for
11273 // wantnormals and wanttangents, so this logic uses only rules applicable
11274 // to a model, knowing that they are meaningless otherwise
11275 if (ent == r_refdef.scene.worldentity)
11276 RSurf_ActiveWorldEntity();
11277 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11278 RSurf_ActiveModelEntity(ent, false, false, false);
11280 RSurf_ActiveModelEntity(ent, true, true, true);
11281 else if (depthonly)
11283 switch (vid.renderpath)
11285 case RENDERPATH_GL20:
11286 case RENDERPATH_D3D9:
11287 case RENDERPATH_D3D10:
11288 case RENDERPATH_D3D11:
11289 case RENDERPATH_SOFT:
11290 case RENDERPATH_GLES2:
11291 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11293 case RENDERPATH_GL13:
11294 case RENDERPATH_GL11:
11295 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11301 switch (vid.renderpath)
11303 case RENDERPATH_GL20:
11304 case RENDERPATH_D3D9:
11305 case RENDERPATH_D3D10:
11306 case RENDERPATH_D3D11:
11307 case RENDERPATH_SOFT:
11308 case RENDERPATH_GLES2:
11309 RSurf_ActiveModelEntity(ent, true, true, false);
11311 case RENDERPATH_GL13:
11312 case RENDERPATH_GL11:
11313 RSurf_ActiveModelEntity(ent, true, false, false);
11318 surfaces = model->data_surfaces;
11319 update = model->brushq1.lightmapupdateflags;
11321 // update light styles
11322 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11324 model_brush_lightstyleinfo_t *style;
11325 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11327 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11329 int *list = style->surfacelist;
11330 style->value = r_refdef.scene.lightstylevalue[style->style];
11331 for (j = 0;j < style->numsurfaces;j++)
11332 update[list[j]] = true;
11337 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11341 R_DrawDebugModel();
11342 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11346 rsurface.lightmaptexture = NULL;
11347 rsurface.deluxemaptexture = NULL;
11348 rsurface.uselightmaptexture = false;
11349 rsurface.texture = NULL;
11350 rsurface.rtlight = NULL;
11351 numsurfacelist = 0;
11352 // add visible surfaces to draw list
11353 for (i = 0;i < model->nummodelsurfaces;i++)
11354 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11355 // don't do anything if there were no surfaces
11356 if (!numsurfacelist)
11358 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11361 // update lightmaps if needed
11365 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11370 R_BuildLightMap(ent, surfaces + j);
11375 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11377 R_BuildLightMap(ent, surfaces + j);
11378 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11380 // add to stats if desired
11381 if (r_speeds.integer && !skysurfaces && !depthonly)
11383 r_refdef.stats.entities_surfaces += numsurfacelist;
11384 for (j = 0;j < numsurfacelist;j++)
11385 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11388 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11391 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11393 static texture_t texture;
11394 static msurface_t surface;
11395 const msurface_t *surfacelist = &surface;
11397 // fake enough texture and surface state to render this geometry
11399 texture.update_lastrenderframe = -1; // regenerate this texture
11400 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11401 texture.currentskinframe = skinframe;
11402 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11403 texture.offsetmapping = OFFSETMAPPING_OFF;
11404 texture.offsetscale = 1;
11405 texture.specularscalemod = 1;
11406 texture.specularpowermod = 1;
11408 surface.texture = &texture;
11409 surface.num_triangles = numtriangles;
11410 surface.num_firsttriangle = firsttriangle;
11411 surface.num_vertices = numvertices;
11412 surface.num_firstvertex = firstvertex;
11415 rsurface.texture = R_GetCurrentTexture(surface.texture);
11416 rsurface.lightmaptexture = NULL;
11417 rsurface.deluxemaptexture = NULL;
11418 rsurface.uselightmaptexture = false;
11419 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11422 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)
11424 static msurface_t surface;
11425 const msurface_t *surfacelist = &surface;
11427 // fake enough texture and surface state to render this geometry
11428 surface.texture = texture;
11429 surface.num_triangles = numtriangles;
11430 surface.num_firsttriangle = firsttriangle;
11431 surface.num_vertices = numvertices;
11432 surface.num_firstvertex = firstvertex;
11435 rsurface.texture = R_GetCurrentTexture(surface.texture);
11436 rsurface.lightmaptexture = NULL;
11437 rsurface.deluxemaptexture = NULL;
11438 rsurface.uselightmaptexture = false;
11439 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);