2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "cl_dyntexture.h"
30 #include "dpsoftrast.h"
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
55 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
56 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
57 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
58 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
60 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
62 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
63 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
64 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
65 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
66 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
68 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
69 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
70 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
71 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
72 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
73 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
74 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
75 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
76 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
77 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
78 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
79 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
80 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
81 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
82 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
83 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
84 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
85 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
86 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
87 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
88 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
89 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
90 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
91 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
92 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
93 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
94 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
95 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
97 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
98 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
99 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
101 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
102 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
103 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
104 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
105 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
106 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
107 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
108 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
109 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
110 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
111 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
112 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
113 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
114 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
115 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
116 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
117 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
118 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
119 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
120 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
122 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
123 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
124 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
125 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
126 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
127 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
128 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
129 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
131 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
132 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
134 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
135 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
136 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
137 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
138 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
140 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
141 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
142 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
144 cvar_t r_viewfbo = {CVAR_SAVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"};
145 cvar_t r_viewscale = {CVAR_SAVE, "r_viewscale", "1", "scaling factor for resolution of the fbo rendering method, must be > 0, can be above 1 for a costly antialiasing behavior, typical values are 0.5 for 1/4th as many pixels rendered, or 1 for normal rendering"};
146 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
147 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
148 cvar_t r_viewscale_fpsscaling_multiply = {CVAR_SAVE, "r_viewscale_fpsscaling_multiply", "5", "adjust quality up or down by the frametime difference from 1.0/target, multiplied by this factor"};
149 cvar_t r_viewscale_fpsscaling_stepsize = {CVAR_SAVE, "r_viewscale_fpsscaling_stepsize", "0.01", "smallest adjustment to hit the target framerate (this value prevents minute oscillations)"};
150 cvar_t r_viewscale_fpsscaling_stepmax = {CVAR_SAVE, "r_viewscale_fpsscaling_stepmax", "1.00", "largest adjustment to hit the target framerate (this value prevents wild overshooting of the estimate)"};
151 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
153 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
154 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
155 cvar_t r_glsl_offsetmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
156 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
157 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
158 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
159 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
160 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
161 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
162 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
163 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
164 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
165 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
166 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
167 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
169 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
170 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
171 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
172 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
173 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
174 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
176 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
177 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
178 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
179 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
181 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
182 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
183 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
184 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
185 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
186 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
187 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
189 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
190 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
191 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
192 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivalent to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
193 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
194 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
195 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
196 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
197 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
198 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
200 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
202 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
204 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
206 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
207 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
208 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
209 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
210 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
211 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
212 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "15", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
213 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
214 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
216 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
217 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
219 cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer."};
221 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
223 extern cvar_t v_glslgamma;
225 extern qboolean v_flipped_state;
227 static struct r_bloomstate_s
232 int bloomwidth, bloomheight;
234 textype_t texturetype;
235 int viewfbo; // used to check if r_viewfbo cvar has changed
237 int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
238 rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
239 rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
241 int screentexturewidth, screentextureheight;
242 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
244 int bloomtexturewidth, bloomtextureheight;
245 rtexture_t *texture_bloom;
247 // arrays for rendering the screen passes
248 float screentexcoord2f[8];
249 float bloomtexcoord2f[8];
250 float offsettexcoord2f[8];
252 r_viewport_t viewport;
256 r_waterstate_t r_waterstate;
258 /// shadow volume bsp struct with automatically growing nodes buffer
261 rtexture_t *r_texture_blanknormalmap;
262 rtexture_t *r_texture_white;
263 rtexture_t *r_texture_grey128;
264 rtexture_t *r_texture_black;
265 rtexture_t *r_texture_notexture;
266 rtexture_t *r_texture_whitecube;
267 rtexture_t *r_texture_normalizationcube;
268 rtexture_t *r_texture_fogattenuation;
269 rtexture_t *r_texture_fogheighttexture;
270 rtexture_t *r_texture_gammaramps;
271 unsigned int r_texture_gammaramps_serial;
272 //rtexture_t *r_texture_fogintensity;
273 rtexture_t *r_texture_reflectcube;
275 // TODO: hash lookups?
276 typedef struct cubemapinfo_s
283 int r_texture_numcubemaps;
284 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
286 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
287 unsigned int r_numqueries;
288 unsigned int r_maxqueries;
290 typedef struct r_qwskincache_s
292 char name[MAX_QPATH];
293 skinframe_t *skinframe;
297 static r_qwskincache_t *r_qwskincache;
298 static int r_qwskincache_size;
300 /// vertex coordinates for a quad that covers the screen exactly
301 extern const float r_screenvertex3f[12];
302 extern const float r_d3dscreenvertex3f[12];
303 const float r_screenvertex3f[12] =
310 const float r_d3dscreenvertex3f[12] =
318 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
321 for (i = 0;i < verts;i++)
332 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
335 for (i = 0;i < verts;i++)
345 // FIXME: move this to client?
348 if (gamemode == GAME_NEHAHRA)
350 Cvar_Set("gl_fogenable", "0");
351 Cvar_Set("gl_fogdensity", "0.2");
352 Cvar_Set("gl_fogred", "0.3");
353 Cvar_Set("gl_foggreen", "0.3");
354 Cvar_Set("gl_fogblue", "0.3");
356 r_refdef.fog_density = 0;
357 r_refdef.fog_red = 0;
358 r_refdef.fog_green = 0;
359 r_refdef.fog_blue = 0;
360 r_refdef.fog_alpha = 1;
361 r_refdef.fog_start = 0;
362 r_refdef.fog_end = 16384;
363 r_refdef.fog_height = 1<<30;
364 r_refdef.fog_fadedepth = 128;
365 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
368 static void R_BuildBlankTextures(void)
370 unsigned char data[4];
371 data[2] = 128; // normal X
372 data[1] = 128; // normal Y
373 data[0] = 255; // normal Z
374 data[3] = 128; // height
375 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
380 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
385 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
390 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
393 static void R_BuildNoTexture(void)
396 unsigned char pix[16][16][4];
397 // this makes a light grey/dark grey checkerboard texture
398 for (y = 0;y < 16;y++)
400 for (x = 0;x < 16;x++)
402 if ((y < 8) ^ (x < 8))
418 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
421 static void R_BuildWhiteCube(void)
423 unsigned char data[6*1*1*4];
424 memset(data, 255, sizeof(data));
425 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
428 static void R_BuildNormalizationCube(void)
432 vec_t s, t, intensity;
435 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
436 for (side = 0;side < 6;side++)
438 for (y = 0;y < NORMSIZE;y++)
440 for (x = 0;x < NORMSIZE;x++)
442 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
443 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
478 intensity = 127.0f / sqrt(DotProduct(v, v));
479 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
480 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
481 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
482 data[((side*64+y)*64+x)*4+3] = 255;
486 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
490 static void R_BuildFogTexture(void)
494 unsigned char data1[FOGWIDTH][4];
495 //unsigned char data2[FOGWIDTH][4];
498 r_refdef.fogmasktable_start = r_refdef.fog_start;
499 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
500 r_refdef.fogmasktable_range = r_refdef.fogrange;
501 r_refdef.fogmasktable_density = r_refdef.fog_density;
503 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
504 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
506 d = (x * r - r_refdef.fogmasktable_start);
507 if(developer_extra.integer)
508 Con_DPrintf("%f ", d);
510 if (r_fog_exp2.integer)
511 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
513 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
514 if(developer_extra.integer)
515 Con_DPrintf(" : %f ", alpha);
516 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
517 if(developer_extra.integer)
518 Con_DPrintf(" = %f\n", alpha);
519 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
522 for (x = 0;x < FOGWIDTH;x++)
524 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
529 //data2[x][0] = 255 - b;
530 //data2[x][1] = 255 - b;
531 //data2[x][2] = 255 - b;
534 if (r_texture_fogattenuation)
536 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
537 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
541 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
542 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
546 static void R_BuildFogHeightTexture(void)
548 unsigned char *inpixels;
556 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
557 if (r_refdef.fogheighttexturename[0])
558 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
561 r_refdef.fog_height_tablesize = 0;
562 if (r_texture_fogheighttexture)
563 R_FreeTexture(r_texture_fogheighttexture);
564 r_texture_fogheighttexture = NULL;
565 if (r_refdef.fog_height_table2d)
566 Mem_Free(r_refdef.fog_height_table2d);
567 r_refdef.fog_height_table2d = NULL;
568 if (r_refdef.fog_height_table1d)
569 Mem_Free(r_refdef.fog_height_table1d);
570 r_refdef.fog_height_table1d = NULL;
574 r_refdef.fog_height_tablesize = size;
575 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
576 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
577 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
579 // LordHavoc: now the magic - what is that table2d for? it is a cooked
580 // average fog color table accounting for every fog layer between a point
581 // and the camera. (Note: attenuation is handled separately!)
582 for (y = 0;y < size;y++)
584 for (x = 0;x < size;x++)
590 for (j = x;j <= y;j++)
592 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
598 for (j = x;j >= y;j--)
600 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
605 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
606 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
607 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
608 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
611 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
614 //=======================================================================================================================================================
616 static const char *builtinshaderstring =
617 #include "shader_glsl.h"
620 const char *builtinhlslshaderstring =
621 #include "shader_hlsl.h"
624 char *glslshaderstring = NULL;
625 char *hlslshaderstring = NULL;
627 //=======================================================================================================================================================
629 typedef struct shaderpermutationinfo_s
634 shaderpermutationinfo_t;
636 typedef struct shadermodeinfo_s
638 const char *vertexfilename;
639 const char *geometryfilename;
640 const char *fragmentfilename;
646 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
647 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
649 {"#define USEDIFFUSE\n", " diffuse"},
650 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
651 {"#define USEVIEWTINT\n", " viewtint"},
652 {"#define USECOLORMAPPING\n", " colormapping"},
653 {"#define USESATURATION\n", " saturation"},
654 {"#define USEFOGINSIDE\n", " foginside"},
655 {"#define USEFOGOUTSIDE\n", " fogoutside"},
656 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
657 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
658 {"#define USEGAMMARAMPS\n", " gammaramps"},
659 {"#define USECUBEFILTER\n", " cubefilter"},
660 {"#define USEGLOW\n", " glow"},
661 {"#define USEBLOOM\n", " bloom"},
662 {"#define USESPECULAR\n", " specular"},
663 {"#define USEPOSTPROCESSING\n", " postprocessing"},
664 {"#define USEREFLECTION\n", " reflection"},
665 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
666 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
667 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
668 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
669 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
670 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
671 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
672 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
673 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
674 {"#define USEALPHAKILL\n", " alphakill"},
675 {"#define USEREFLECTCUBE\n", " reflectcube"},
676 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
677 {"#define USEBOUNCEGRID\n", " bouncegrid"},
678 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
681 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
682 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
684 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
685 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
686 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
687 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
688 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
689 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
690 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
691 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
692 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
693 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
694 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
695 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
696 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
697 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
698 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
699 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
702 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
704 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
705 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
706 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
707 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
708 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
709 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
710 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
711 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
712 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
713 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
714 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
715 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
716 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
717 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
718 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
719 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
722 struct r_glsl_permutation_s;
723 typedef struct r_glsl_permutation_s
726 struct r_glsl_permutation_s *hashnext;
728 unsigned int permutation;
730 /// indicates if we have tried compiling this permutation already
732 /// 0 if compilation failed
734 // texture units assigned to each detected uniform
735 int tex_Texture_First;
736 int tex_Texture_Second;
737 int tex_Texture_GammaRamps;
738 int tex_Texture_Normal;
739 int tex_Texture_Color;
740 int tex_Texture_Gloss;
741 int tex_Texture_Glow;
742 int tex_Texture_SecondaryNormal;
743 int tex_Texture_SecondaryColor;
744 int tex_Texture_SecondaryGloss;
745 int tex_Texture_SecondaryGlow;
746 int tex_Texture_Pants;
747 int tex_Texture_Shirt;
748 int tex_Texture_FogHeightTexture;
749 int tex_Texture_FogMask;
750 int tex_Texture_Lightmap;
751 int tex_Texture_Deluxemap;
752 int tex_Texture_Attenuation;
753 int tex_Texture_Cube;
754 int tex_Texture_Refraction;
755 int tex_Texture_Reflection;
756 int tex_Texture_ShadowMap2D;
757 int tex_Texture_CubeProjection;
758 int tex_Texture_ScreenDepth;
759 int tex_Texture_ScreenNormalMap;
760 int tex_Texture_ScreenDiffuse;
761 int tex_Texture_ScreenSpecular;
762 int tex_Texture_ReflectMask;
763 int tex_Texture_ReflectCube;
764 int tex_Texture_BounceGrid;
765 /// locations of detected uniforms in program object, or -1 if not found
766 int loc_Texture_First;
767 int loc_Texture_Second;
768 int loc_Texture_GammaRamps;
769 int loc_Texture_Normal;
770 int loc_Texture_Color;
771 int loc_Texture_Gloss;
772 int loc_Texture_Glow;
773 int loc_Texture_SecondaryNormal;
774 int loc_Texture_SecondaryColor;
775 int loc_Texture_SecondaryGloss;
776 int loc_Texture_SecondaryGlow;
777 int loc_Texture_Pants;
778 int loc_Texture_Shirt;
779 int loc_Texture_FogHeightTexture;
780 int loc_Texture_FogMask;
781 int loc_Texture_Lightmap;
782 int loc_Texture_Deluxemap;
783 int loc_Texture_Attenuation;
784 int loc_Texture_Cube;
785 int loc_Texture_Refraction;
786 int loc_Texture_Reflection;
787 int loc_Texture_ShadowMap2D;
788 int loc_Texture_CubeProjection;
789 int loc_Texture_ScreenDepth;
790 int loc_Texture_ScreenNormalMap;
791 int loc_Texture_ScreenDiffuse;
792 int loc_Texture_ScreenSpecular;
793 int loc_Texture_ReflectMask;
794 int loc_Texture_ReflectCube;
795 int loc_Texture_BounceGrid;
797 int loc_BloomBlur_Parameters;
799 int loc_Color_Ambient;
800 int loc_Color_Diffuse;
801 int loc_Color_Specular;
805 int loc_DeferredColor_Ambient;
806 int loc_DeferredColor_Diffuse;
807 int loc_DeferredColor_Specular;
808 int loc_DeferredMod_Diffuse;
809 int loc_DeferredMod_Specular;
810 int loc_DistortScaleRefractReflect;
813 int loc_FogHeightFade;
815 int loc_FogPlaneViewDist;
816 int loc_FogRangeRecip;
819 int loc_LightPosition;
820 int loc_OffsetMapping_ScaleSteps;
822 int loc_ReflectColor;
823 int loc_ReflectFactor;
824 int loc_ReflectOffset;
825 int loc_RefractColor;
827 int loc_ScreenCenterRefractReflect;
828 int loc_ScreenScaleRefractReflect;
829 int loc_ScreenToDepth;
830 int loc_ShadowMap_Parameters;
831 int loc_ShadowMap_TextureScale;
832 int loc_SpecularPower;
837 int loc_ViewTintColor;
839 int loc_ModelToLight;
841 int loc_BackgroundTexMatrix;
842 int loc_ModelViewProjectionMatrix;
843 int loc_ModelViewMatrix;
844 int loc_PixelToScreenTexCoord;
845 int loc_ModelToReflectCube;
846 int loc_ShadowMapMatrix;
847 int loc_BloomColorSubtract;
848 int loc_NormalmapScrollBlend;
849 int loc_BounceGridMatrix;
850 int loc_BounceGridIntensity;
852 r_glsl_permutation_t;
854 #define SHADERPERMUTATION_HASHSIZE 256
857 // non-degradable "lightweight" shader parameters to keep the permutations simpler
858 // these can NOT degrade! only use for simple stuff
861 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
862 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
863 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
864 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
865 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
866 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
867 SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
869 #define SHADERSTATICPARMS_COUNT 7
871 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
872 static int shaderstaticparms_count = 0;
874 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
875 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
876 qboolean R_CompileShader_CheckStaticParms(void)
878 static int r_compileshader_staticparms_save[1];
879 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
880 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
883 if (r_glsl_saturation_redcompensate.integer)
884 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
885 if (r_glsl_vertextextureblend_usebothalphas.integer)
886 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
887 if (r_shadow_glossexact.integer)
888 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
889 if (r_glsl_postprocess.integer)
891 if (r_glsl_postprocess_uservec1_enable.integer)
892 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
893 if (r_glsl_postprocess_uservec2_enable.integer)
894 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
895 if (r_glsl_postprocess_uservec3_enable.integer)
896 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
897 if (r_glsl_postprocess_uservec4_enable.integer)
898 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
900 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
903 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
904 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
905 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
907 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
908 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
910 shaderstaticparms_count = 0;
913 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
914 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
915 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
916 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
917 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
918 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
919 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
922 /// information about each possible shader permutation
923 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
924 /// currently selected permutation
925 r_glsl_permutation_t *r_glsl_permutation;
926 /// storage for permutations linked in the hash table
927 memexpandablearray_t r_glsl_permutationarray;
929 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
931 //unsigned int hashdepth = 0;
932 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
933 r_glsl_permutation_t *p;
934 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
936 if (p->mode == mode && p->permutation == permutation)
938 //if (hashdepth > 10)
939 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
944 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
946 p->permutation = permutation;
947 p->hashnext = r_glsl_permutationhash[mode][hashindex];
948 r_glsl_permutationhash[mode][hashindex] = p;
949 //if (hashdepth > 10)
950 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
954 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
957 if (!filename || !filename[0])
959 if (!strcmp(filename, "glsl/default.glsl"))
961 if (!glslshaderstring)
963 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
964 if (glslshaderstring)
965 Con_DPrintf("Loading shaders from file %s...\n", filename);
967 glslshaderstring = (char *)builtinshaderstring;
969 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
970 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
973 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
976 if (printfromdisknotice)
977 Con_DPrintf("from disk %s... ", filename);
983 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
987 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
988 char *vertexstring, *geometrystring, *fragmentstring;
989 char permutationname[256];
990 int vertstrings_count = 0;
991 int geomstrings_count = 0;
992 int fragstrings_count = 0;
993 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
994 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
995 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1002 permutationname[0] = 0;
1003 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1004 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1005 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1007 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1009 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1010 if(vid.support.gl20shaders130)
1012 vertstrings_list[vertstrings_count++] = "#version 130\n";
1013 geomstrings_list[geomstrings_count++] = "#version 130\n";
1014 fragstrings_list[fragstrings_count++] = "#version 130\n";
1015 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1016 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1017 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1020 // the first pretext is which type of shader to compile as
1021 // (later these will all be bound together as a program object)
1022 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1023 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1024 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1026 // the second pretext is the mode (for example a light source)
1027 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1028 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1029 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1030 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1032 // now add all the permutation pretexts
1033 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1035 if (permutation & (1<<i))
1037 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1038 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1039 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1040 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1044 // keep line numbers correct
1045 vertstrings_list[vertstrings_count++] = "\n";
1046 geomstrings_list[geomstrings_count++] = "\n";
1047 fragstrings_list[fragstrings_count++] = "\n";
1052 R_CompileShader_AddStaticParms(mode, permutation);
1053 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1054 vertstrings_count += shaderstaticparms_count;
1055 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1056 geomstrings_count += shaderstaticparms_count;
1057 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1058 fragstrings_count += shaderstaticparms_count;
1060 // now append the shader text itself
1061 vertstrings_list[vertstrings_count++] = vertexstring;
1062 geomstrings_list[geomstrings_count++] = geometrystring;
1063 fragstrings_list[fragstrings_count++] = fragmentstring;
1065 // if any sources were NULL, clear the respective list
1067 vertstrings_count = 0;
1068 if (!geometrystring)
1069 geomstrings_count = 0;
1070 if (!fragmentstring)
1071 fragstrings_count = 0;
1073 // compile the shader program
1074 if (vertstrings_count + geomstrings_count + fragstrings_count)
1075 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1079 qglUseProgram(p->program);CHECKGLERROR
1080 // look up all the uniform variable names we care about, so we don't
1081 // have to look them up every time we set them
1083 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1084 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1085 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1086 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1087 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1088 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1089 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1090 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1091 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1092 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1093 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1094 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1095 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1096 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1097 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1098 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1099 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1100 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1101 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1102 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1103 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1104 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1105 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1106 p->loc_Texture_ScreenDepth = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1107 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1108 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1109 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1110 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1111 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1112 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1113 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1114 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1115 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1116 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1117 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1118 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1119 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1120 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1121 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1122 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1123 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1124 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1125 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1126 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1127 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1128 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1129 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1130 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1131 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1132 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1133 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1134 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1135 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1136 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1137 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1138 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1139 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1140 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1141 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1142 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1143 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1144 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1145 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1146 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1147 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1148 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1149 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1150 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1151 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1152 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1153 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1154 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1155 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1156 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1157 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1158 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1159 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1160 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1161 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1162 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1163 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1164 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1165 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1166 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1167 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1168 // initialize the samplers to refer to the texture units we use
1169 p->tex_Texture_First = -1;
1170 p->tex_Texture_Second = -1;
1171 p->tex_Texture_GammaRamps = -1;
1172 p->tex_Texture_Normal = -1;
1173 p->tex_Texture_Color = -1;
1174 p->tex_Texture_Gloss = -1;
1175 p->tex_Texture_Glow = -1;
1176 p->tex_Texture_SecondaryNormal = -1;
1177 p->tex_Texture_SecondaryColor = -1;
1178 p->tex_Texture_SecondaryGloss = -1;
1179 p->tex_Texture_SecondaryGlow = -1;
1180 p->tex_Texture_Pants = -1;
1181 p->tex_Texture_Shirt = -1;
1182 p->tex_Texture_FogHeightTexture = -1;
1183 p->tex_Texture_FogMask = -1;
1184 p->tex_Texture_Lightmap = -1;
1185 p->tex_Texture_Deluxemap = -1;
1186 p->tex_Texture_Attenuation = -1;
1187 p->tex_Texture_Cube = -1;
1188 p->tex_Texture_Refraction = -1;
1189 p->tex_Texture_Reflection = -1;
1190 p->tex_Texture_ShadowMap2D = -1;
1191 p->tex_Texture_CubeProjection = -1;
1192 p->tex_Texture_ScreenDepth = -1;
1193 p->tex_Texture_ScreenNormalMap = -1;
1194 p->tex_Texture_ScreenDiffuse = -1;
1195 p->tex_Texture_ScreenSpecular = -1;
1196 p->tex_Texture_ReflectMask = -1;
1197 p->tex_Texture_ReflectCube = -1;
1198 p->tex_Texture_BounceGrid = -1;
1200 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1201 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1202 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1203 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1204 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1205 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1206 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1207 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1208 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1209 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1210 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1211 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1212 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1213 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1214 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1215 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1216 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1217 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1218 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1219 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1220 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1221 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1222 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1223 if (p->loc_Texture_ScreenDepth >= 0) {p->tex_Texture_ScreenDepth = sampler;qglUniform1i(p->loc_Texture_ScreenDepth , sampler);sampler++;}
1224 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1225 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1226 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1227 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1228 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1229 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1231 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1234 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1238 Mem_Free(vertexstring);
1240 Mem_Free(geometrystring);
1242 Mem_Free(fragmentstring);
1245 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1247 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1248 if (r_glsl_permutation != perm)
1250 r_glsl_permutation = perm;
1251 if (!r_glsl_permutation->program)
1253 if (!r_glsl_permutation->compiled)
1254 R_GLSL_CompilePermutation(perm, mode, permutation);
1255 if (!r_glsl_permutation->program)
1257 // remove features until we find a valid permutation
1259 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1261 // reduce i more quickly whenever it would not remove any bits
1262 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1263 if (!(permutation & j))
1266 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1267 if (!r_glsl_permutation->compiled)
1268 R_GLSL_CompilePermutation(perm, mode, permutation);
1269 if (r_glsl_permutation->program)
1272 if (i >= SHADERPERMUTATION_COUNT)
1274 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1275 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1276 qglUseProgram(0);CHECKGLERROR
1277 return; // no bit left to clear, entire mode is broken
1282 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1284 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1285 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1286 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1293 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1294 extern D3DCAPS9 vid_d3d9caps;
1297 struct r_hlsl_permutation_s;
1298 typedef struct r_hlsl_permutation_s
1300 /// hash lookup data
1301 struct r_hlsl_permutation_s *hashnext;
1303 unsigned int permutation;
1305 /// indicates if we have tried compiling this permutation already
1307 /// NULL if compilation failed
1308 IDirect3DVertexShader9 *vertexshader;
1309 IDirect3DPixelShader9 *pixelshader;
1311 r_hlsl_permutation_t;
1313 typedef enum D3DVSREGISTER_e
1315 D3DVSREGISTER_TexMatrix = 0, // float4x4
1316 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1317 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1318 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1319 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1320 D3DVSREGISTER_ModelToLight = 20, // float4x4
1321 D3DVSREGISTER_EyePosition = 24,
1322 D3DVSREGISTER_FogPlane = 25,
1323 D3DVSREGISTER_LightDir = 26,
1324 D3DVSREGISTER_LightPosition = 27,
1328 typedef enum D3DPSREGISTER_e
1330 D3DPSREGISTER_Alpha = 0,
1331 D3DPSREGISTER_BloomBlur_Parameters = 1,
1332 D3DPSREGISTER_ClientTime = 2,
1333 D3DPSREGISTER_Color_Ambient = 3,
1334 D3DPSREGISTER_Color_Diffuse = 4,
1335 D3DPSREGISTER_Color_Specular = 5,
1336 D3DPSREGISTER_Color_Glow = 6,
1337 D3DPSREGISTER_Color_Pants = 7,
1338 D3DPSREGISTER_Color_Shirt = 8,
1339 D3DPSREGISTER_DeferredColor_Ambient = 9,
1340 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1341 D3DPSREGISTER_DeferredColor_Specular = 11,
1342 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1343 D3DPSREGISTER_DeferredMod_Specular = 13,
1344 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1345 D3DPSREGISTER_EyePosition = 15, // unused
1346 D3DPSREGISTER_FogColor = 16,
1347 D3DPSREGISTER_FogHeightFade = 17,
1348 D3DPSREGISTER_FogPlane = 18,
1349 D3DPSREGISTER_FogPlaneViewDist = 19,
1350 D3DPSREGISTER_FogRangeRecip = 20,
1351 D3DPSREGISTER_LightColor = 21,
1352 D3DPSREGISTER_LightDir = 22, // unused
1353 D3DPSREGISTER_LightPosition = 23,
1354 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1355 D3DPSREGISTER_PixelSize = 25,
1356 D3DPSREGISTER_ReflectColor = 26,
1357 D3DPSREGISTER_ReflectFactor = 27,
1358 D3DPSREGISTER_ReflectOffset = 28,
1359 D3DPSREGISTER_RefractColor = 29,
1360 D3DPSREGISTER_Saturation = 30,
1361 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1362 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1363 D3DPSREGISTER_ScreenToDepth = 33,
1364 D3DPSREGISTER_ShadowMap_Parameters = 34,
1365 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1366 D3DPSREGISTER_SpecularPower = 36,
1367 D3DPSREGISTER_UserVec1 = 37,
1368 D3DPSREGISTER_UserVec2 = 38,
1369 D3DPSREGISTER_UserVec3 = 39,
1370 D3DPSREGISTER_UserVec4 = 40,
1371 D3DPSREGISTER_ViewTintColor = 41,
1372 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1373 D3DPSREGISTER_BloomColorSubtract = 43,
1374 D3DPSREGISTER_ViewToLight = 44, // float4x4
1375 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1376 D3DPSREGISTER_NormalmapScrollBlend = 52,
1381 /// information about each possible shader permutation
1382 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1383 /// currently selected permutation
1384 r_hlsl_permutation_t *r_hlsl_permutation;
1385 /// storage for permutations linked in the hash table
1386 memexpandablearray_t r_hlsl_permutationarray;
1388 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1390 //unsigned int hashdepth = 0;
1391 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1392 r_hlsl_permutation_t *p;
1393 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1395 if (p->mode == mode && p->permutation == permutation)
1397 //if (hashdepth > 10)
1398 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1403 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1405 p->permutation = permutation;
1406 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1407 r_hlsl_permutationhash[mode][hashindex] = p;
1408 //if (hashdepth > 10)
1409 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1413 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1416 if (!filename || !filename[0])
1418 if (!strcmp(filename, "hlsl/default.hlsl"))
1420 if (!hlslshaderstring)
1422 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1423 if (hlslshaderstring)
1424 Con_DPrintf("Loading shaders from file %s...\n", filename);
1426 hlslshaderstring = (char *)builtinhlslshaderstring;
1428 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1429 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1430 return shaderstring;
1432 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1435 if (printfromdisknotice)
1436 Con_DPrintf("from disk %s... ", filename);
1437 return shaderstring;
1439 return shaderstring;
1443 //#include <d3dx9shader.h>
1444 //#include <d3dx9mesh.h>
1446 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1448 DWORD *vsbin = NULL;
1449 DWORD *psbin = NULL;
1450 fs_offset_t vsbinsize;
1451 fs_offset_t psbinsize;
1452 // IDirect3DVertexShader9 *vs = NULL;
1453 // IDirect3DPixelShader9 *ps = NULL;
1454 ID3DXBuffer *vslog = NULL;
1455 ID3DXBuffer *vsbuffer = NULL;
1456 ID3DXConstantTable *vsconstanttable = NULL;
1457 ID3DXBuffer *pslog = NULL;
1458 ID3DXBuffer *psbuffer = NULL;
1459 ID3DXConstantTable *psconstanttable = NULL;
1462 char temp[MAX_INPUTLINE];
1463 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1464 qboolean debugshader = gl_paranoid.integer != 0;
1465 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1466 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1469 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1470 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1472 if ((!vsbin && vertstring) || (!psbin && fragstring))
1474 const char* dllnames_d3dx9 [] =
1498 dllhandle_t d3dx9_dll = NULL;
1499 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1500 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1501 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1502 dllfunction_t d3dx9_dllfuncs[] =
1504 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1505 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1506 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1509 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1511 DWORD shaderflags = 0;
1513 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1514 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1515 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1516 if (vertstring && vertstring[0])
1520 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1521 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1522 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1523 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1526 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1529 vsbinsize = vsbuffer->GetBufferSize();
1530 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1531 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1532 vsbuffer->Release();
1536 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1537 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1541 if (fragstring && fragstring[0])
1545 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1546 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1547 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1548 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1551 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1554 psbinsize = psbuffer->GetBufferSize();
1555 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1556 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1557 psbuffer->Release();
1561 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1562 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1566 Sys_UnloadLibrary(&d3dx9_dll);
1569 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1573 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1574 if (FAILED(vsresult))
1575 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1576 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1577 if (FAILED(psresult))
1578 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1580 // free the shader data
1581 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1582 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1585 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1588 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1589 int vertstring_length = 0;
1590 int geomstring_length = 0;
1591 int fragstring_length = 0;
1593 char *vertexstring, *geometrystring, *fragmentstring;
1594 char *vertstring, *geomstring, *fragstring;
1595 char permutationname[256];
1596 char cachename[256];
1597 int vertstrings_count = 0;
1598 int geomstrings_count = 0;
1599 int fragstrings_count = 0;
1600 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1601 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1602 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1607 p->vertexshader = NULL;
1608 p->pixelshader = NULL;
1610 permutationname[0] = 0;
1612 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
1613 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1614 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1616 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1617 strlcat(cachename, "hlsl/", sizeof(cachename));
1619 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1620 vertstrings_count = 0;
1621 geomstrings_count = 0;
1622 fragstrings_count = 0;
1623 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1624 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1625 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1627 // the first pretext is which type of shader to compile as
1628 // (later these will all be bound together as a program object)
1629 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1630 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1631 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1633 // the second pretext is the mode (for example a light source)
1634 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1635 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1636 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1637 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1638 strlcat(cachename, modeinfo->name, sizeof(cachename));
1640 // now add all the permutation pretexts
1641 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1643 if (permutation & (1<<i))
1645 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1646 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1647 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1648 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1649 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1653 // keep line numbers correct
1654 vertstrings_list[vertstrings_count++] = "\n";
1655 geomstrings_list[geomstrings_count++] = "\n";
1656 fragstrings_list[fragstrings_count++] = "\n";
1661 R_CompileShader_AddStaticParms(mode, permutation);
1662 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1663 vertstrings_count += shaderstaticparms_count;
1664 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1665 geomstrings_count += shaderstaticparms_count;
1666 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1667 fragstrings_count += shaderstaticparms_count;
1669 // replace spaces in the cachename with _ characters
1670 for (i = 0;cachename[i];i++)
1671 if (cachename[i] == ' ')
1674 // now append the shader text itself
1675 vertstrings_list[vertstrings_count++] = vertexstring;
1676 geomstrings_list[geomstrings_count++] = geometrystring;
1677 fragstrings_list[fragstrings_count++] = fragmentstring;
1679 // if any sources were NULL, clear the respective list
1681 vertstrings_count = 0;
1682 if (!geometrystring)
1683 geomstrings_count = 0;
1684 if (!fragmentstring)
1685 fragstrings_count = 0;
1687 vertstring_length = 0;
1688 for (i = 0;i < vertstrings_count;i++)
1689 vertstring_length += strlen(vertstrings_list[i]);
1690 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1691 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1692 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1694 geomstring_length = 0;
1695 for (i = 0;i < geomstrings_count;i++)
1696 geomstring_length += strlen(geomstrings_list[i]);
1697 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1698 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1699 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1701 fragstring_length = 0;
1702 for (i = 0;i < fragstrings_count;i++)
1703 fragstring_length += strlen(fragstrings_list[i]);
1704 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1705 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1706 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1708 // try to load the cached shader, or generate one
1709 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1711 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1712 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1714 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1718 Mem_Free(vertstring);
1720 Mem_Free(geomstring);
1722 Mem_Free(fragstring);
1724 Mem_Free(vertexstring);
1726 Mem_Free(geometrystring);
1728 Mem_Free(fragmentstring);
1731 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1732 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1733 static inline void hlslVSSetParameter4f(D3DVSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1734 static inline void hlslVSSetParameter3f(D3DVSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1735 static inline void hlslVSSetParameter2f(D3DVSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1736 static inline void hlslVSSetParameter1f(D3DVSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1738 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1739 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1740 static inline void hlslPSSetParameter4f(D3DPSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1741 static inline void hlslPSSetParameter3f(D3DPSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1742 static inline void hlslPSSetParameter2f(D3DPSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1743 static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1745 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1747 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1748 if (r_hlsl_permutation != perm)
1750 r_hlsl_permutation = perm;
1751 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1753 if (!r_hlsl_permutation->compiled)
1754 R_HLSL_CompilePermutation(perm, mode, permutation);
1755 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1757 // remove features until we find a valid permutation
1759 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1761 // reduce i more quickly whenever it would not remove any bits
1762 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1763 if (!(permutation & j))
1766 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1767 if (!r_hlsl_permutation->compiled)
1768 R_HLSL_CompilePermutation(perm, mode, permutation);
1769 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1772 if (i >= SHADERPERMUTATION_COUNT)
1774 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1775 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1776 return; // no bit left to clear, entire mode is broken
1780 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1781 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1783 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1784 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1785 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1789 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1791 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1792 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1793 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1794 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1797 void R_GLSL_Restart_f(void)
1799 unsigned int i, limit;
1800 if (glslshaderstring && glslshaderstring != builtinshaderstring)
1801 Mem_Free(glslshaderstring);
1802 glslshaderstring = NULL;
1803 if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1804 Mem_Free(hlslshaderstring);
1805 hlslshaderstring = NULL;
1806 switch(vid.renderpath)
1808 case RENDERPATH_D3D9:
1811 r_hlsl_permutation_t *p;
1812 r_hlsl_permutation = NULL;
1813 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1814 for (i = 0;i < limit;i++)
1816 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1818 if (p->vertexshader)
1819 IDirect3DVertexShader9_Release(p->vertexshader);
1821 IDirect3DPixelShader9_Release(p->pixelshader);
1822 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1825 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1829 case RENDERPATH_D3D10:
1830 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1832 case RENDERPATH_D3D11:
1833 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1835 case RENDERPATH_GL20:
1836 case RENDERPATH_GLES2:
1838 r_glsl_permutation_t *p;
1839 r_glsl_permutation = NULL;
1840 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1841 for (i = 0;i < limit;i++)
1843 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1845 GL_Backend_FreeProgram(p->program);
1846 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1849 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1852 case RENDERPATH_GL13:
1853 case RENDERPATH_GL11:
1855 case RENDERPATH_SOFT:
1860 void R_GLSL_DumpShader_f(void)
1865 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1868 FS_Print(file, "/* The engine may define the following macros:\n");
1869 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1870 for (i = 0;i < SHADERMODE_COUNT;i++)
1871 FS_Print(file, glslshadermodeinfo[i].pretext);
1872 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1873 FS_Print(file, shaderpermutationinfo[i].pretext);
1874 FS_Print(file, "*/\n");
1875 FS_Print(file, builtinshaderstring);
1877 Con_Printf("glsl/default.glsl written\n");
1880 Con_Printf("failed to write to glsl/default.glsl\n");
1882 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1885 FS_Print(file, "/* The engine may define the following macros:\n");
1886 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1887 for (i = 0;i < SHADERMODE_COUNT;i++)
1888 FS_Print(file, hlslshadermodeinfo[i].pretext);
1889 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1890 FS_Print(file, shaderpermutationinfo[i].pretext);
1891 FS_Print(file, "*/\n");
1892 FS_Print(file, builtinhlslshaderstring);
1894 Con_Printf("hlsl/default.hlsl written\n");
1897 Con_Printf("failed to write to hlsl/default.hlsl\n");
1900 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1903 texturemode = GL_MODULATE;
1904 switch (vid.renderpath)
1906 case RENDERPATH_D3D9:
1908 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1909 R_Mesh_TexBind(GL20TU_FIRST , first );
1910 R_Mesh_TexBind(GL20TU_SECOND, second);
1913 case RENDERPATH_D3D10:
1914 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1916 case RENDERPATH_D3D11:
1917 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1919 case RENDERPATH_GL20:
1920 case RENDERPATH_GLES2:
1921 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1922 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1923 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1925 case RENDERPATH_GL13:
1926 R_Mesh_TexBind(0, first );
1927 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1928 R_Mesh_TexBind(1, second);
1930 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1932 case RENDERPATH_GL11:
1933 R_Mesh_TexBind(0, first );
1935 case RENDERPATH_SOFT:
1936 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1937 R_Mesh_TexBind(GL20TU_FIRST , first );
1938 R_Mesh_TexBind(GL20TU_SECOND, second);
1943 void R_SetupShader_DepthOrShadow(void)
1945 switch (vid.renderpath)
1947 case RENDERPATH_D3D9:
1949 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1952 case RENDERPATH_D3D10:
1953 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1955 case RENDERPATH_D3D11:
1956 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1958 case RENDERPATH_GL20:
1959 case RENDERPATH_GLES2:
1960 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1962 case RENDERPATH_GL13:
1963 R_Mesh_TexBind(0, 0);
1964 R_Mesh_TexBind(1, 0);
1966 case RENDERPATH_GL11:
1967 R_Mesh_TexBind(0, 0);
1969 case RENDERPATH_SOFT:
1970 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1975 void R_SetupShader_ShowDepth(void)
1977 switch (vid.renderpath)
1979 case RENDERPATH_D3D9:
1981 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1984 case RENDERPATH_D3D10:
1985 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1987 case RENDERPATH_D3D11:
1988 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1990 case RENDERPATH_GL20:
1991 case RENDERPATH_GLES2:
1992 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1994 case RENDERPATH_GL13:
1996 case RENDERPATH_GL11:
1998 case RENDERPATH_SOFT:
1999 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
2004 extern qboolean r_shadow_usingdeferredprepass;
2005 extern cvar_t r_shadow_deferred_8bitrange;
2006 extern rtexture_t *r_shadow_attenuationgradienttexture;
2007 extern rtexture_t *r_shadow_attenuation2dtexture;
2008 extern rtexture_t *r_shadow_attenuation3dtexture;
2009 extern qboolean r_shadow_usingshadowmap2d;
2010 extern qboolean r_shadow_usingshadowmaportho;
2011 extern float r_shadow_shadowmap_texturescale[2];
2012 extern float r_shadow_shadowmap_parameters[4];
2013 extern qboolean r_shadow_shadowmapvsdct;
2014 extern qboolean r_shadow_shadowmapsampler;
2015 extern int r_shadow_shadowmappcf;
2016 extern rtexture_t *r_shadow_shadowmap2dtexture;
2017 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2018 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2019 extern matrix4x4_t r_shadow_shadowmapmatrix;
2020 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2021 extern int r_shadow_prepass_width;
2022 extern int r_shadow_prepass_height;
2023 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2024 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2025 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2026 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2027 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2029 #define BLENDFUNC_ALLOWS_COLORMOD 1
2030 #define BLENDFUNC_ALLOWS_FOG 2
2031 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2032 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2033 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2034 static int R_BlendFuncFlags(int src, int dst)
2038 // a blendfunc allows colormod if:
2039 // a) it can never keep the destination pixel invariant, or
2040 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2041 // this is to prevent unintended side effects from colormod
2043 // a blendfunc allows fog if:
2044 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2045 // this is to prevent unintended side effects from fog
2047 // these checks are the output of fogeval.pl
2049 r |= BLENDFUNC_ALLOWS_COLORMOD;
2050 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2051 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2052 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2053 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2054 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2055 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2056 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2057 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2058 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2059 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2060 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2061 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2062 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2063 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2064 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2065 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2066 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2067 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2068 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2069 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2070 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2075 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane)
2077 // select a permutation of the lighting shader appropriate to this
2078 // combination of texture, entity, light source, and fogging, only use the
2079 // minimum features necessary to avoid wasting rendering time in the
2080 // fragment shader on features that are not being used
2081 unsigned int permutation = 0;
2082 unsigned int mode = 0;
2084 static float dummy_colormod[3] = {1, 1, 1};
2085 float *colormod = rsurface.colormod;
2087 matrix4x4_t tempmatrix;
2088 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2089 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2090 permutation |= SHADERPERMUTATION_ALPHAKILL;
2091 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2092 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2093 if (rsurfacepass == RSURFPASS_BACKGROUND)
2095 // distorted background
2096 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2098 mode = SHADERMODE_WATER;
2099 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2101 // this is the right thing to do for wateralpha
2102 GL_BlendFunc(GL_ONE, GL_ZERO);
2103 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2107 // this is the right thing to do for entity alpha
2108 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2109 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2112 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2114 mode = SHADERMODE_REFRACTION;
2115 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2116 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2120 mode = SHADERMODE_GENERIC;
2121 permutation |= SHADERPERMUTATION_DIFFUSE;
2122 GL_BlendFunc(GL_ONE, GL_ZERO);
2123 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2126 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2128 if (r_glsl_offsetmapping.integer)
2130 switch(rsurface.texture->offsetmapping)
2132 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2133 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2134 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2135 case OFFSETMAPPING_OFF: break;
2138 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2139 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2140 // normalmap (deferred prepass), may use alpha test on diffuse
2141 mode = SHADERMODE_DEFERREDGEOMETRY;
2142 GL_BlendFunc(GL_ONE, GL_ZERO);
2143 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2145 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2147 if (r_glsl_offsetmapping.integer)
2149 switch(rsurface.texture->offsetmapping)
2151 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2152 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2153 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2154 case OFFSETMAPPING_OFF: break;
2157 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2158 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2160 mode = SHADERMODE_LIGHTSOURCE;
2161 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2162 permutation |= SHADERPERMUTATION_CUBEFILTER;
2163 if (diffusescale > 0)
2164 permutation |= SHADERPERMUTATION_DIFFUSE;
2165 if (specularscale > 0)
2166 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2167 if (r_refdef.fogenabled)
2168 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2169 if (rsurface.texture->colormapping)
2170 permutation |= SHADERPERMUTATION_COLORMAPPING;
2171 if (r_shadow_usingshadowmap2d)
2173 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2174 if(r_shadow_shadowmapvsdct)
2175 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2177 if (r_shadow_shadowmapsampler)
2178 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2179 if (r_shadow_shadowmappcf > 1)
2180 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2181 else if (r_shadow_shadowmappcf)
2182 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2184 if (rsurface.texture->reflectmasktexture)
2185 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2186 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2187 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2189 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2191 if (r_glsl_offsetmapping.integer)
2193 switch(rsurface.texture->offsetmapping)
2195 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2196 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2197 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2198 case OFFSETMAPPING_OFF: break;
2201 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2202 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2203 // unshaded geometry (fullbright or ambient model lighting)
2204 mode = SHADERMODE_FLATCOLOR;
2205 ambientscale = diffusescale = specularscale = 0;
2206 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2207 permutation |= SHADERPERMUTATION_GLOW;
2208 if (r_refdef.fogenabled)
2209 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2210 if (rsurface.texture->colormapping)
2211 permutation |= SHADERPERMUTATION_COLORMAPPING;
2212 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2214 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2215 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2217 if (r_shadow_shadowmapsampler)
2218 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2219 if (r_shadow_shadowmappcf > 1)
2220 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2221 else if (r_shadow_shadowmappcf)
2222 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2224 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2225 permutation |= SHADERPERMUTATION_REFLECTION;
2226 if (rsurface.texture->reflectmasktexture)
2227 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2228 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2229 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2231 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2233 if (r_glsl_offsetmapping.integer)
2235 switch(rsurface.texture->offsetmapping)
2237 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2238 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2239 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2240 case OFFSETMAPPING_OFF: break;
2243 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2244 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2245 // directional model lighting
2246 mode = SHADERMODE_LIGHTDIRECTION;
2247 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2248 permutation |= SHADERPERMUTATION_GLOW;
2249 permutation |= SHADERPERMUTATION_DIFFUSE;
2250 if (specularscale > 0)
2251 permutation |= SHADERPERMUTATION_SPECULAR;
2252 if (r_refdef.fogenabled)
2253 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2254 if (rsurface.texture->colormapping)
2255 permutation |= SHADERPERMUTATION_COLORMAPPING;
2256 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2258 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2259 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2261 if (r_shadow_shadowmapsampler)
2262 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2263 if (r_shadow_shadowmappcf > 1)
2264 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2265 else if (r_shadow_shadowmappcf)
2266 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2268 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2269 permutation |= SHADERPERMUTATION_REFLECTION;
2270 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2271 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2272 if (rsurface.texture->reflectmasktexture)
2273 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2274 if (r_shadow_bouncegridtexture)
2276 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2277 if (r_shadow_bouncegriddirectional)
2278 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2280 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2281 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2283 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2285 if (r_glsl_offsetmapping.integer)
2287 switch(rsurface.texture->offsetmapping)
2289 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2290 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2291 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2292 case OFFSETMAPPING_OFF: break;
2295 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2296 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2297 // ambient model lighting
2298 mode = SHADERMODE_LIGHTDIRECTION;
2299 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2300 permutation |= SHADERPERMUTATION_GLOW;
2301 if (r_refdef.fogenabled)
2302 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2303 if (rsurface.texture->colormapping)
2304 permutation |= SHADERPERMUTATION_COLORMAPPING;
2305 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2307 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2308 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2310 if (r_shadow_shadowmapsampler)
2311 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2312 if (r_shadow_shadowmappcf > 1)
2313 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2314 else if (r_shadow_shadowmappcf)
2315 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2317 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2318 permutation |= SHADERPERMUTATION_REFLECTION;
2319 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2320 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2321 if (rsurface.texture->reflectmasktexture)
2322 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2323 if (r_shadow_bouncegridtexture)
2325 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2326 if (r_shadow_bouncegriddirectional)
2327 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2329 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2330 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2334 if (r_glsl_offsetmapping.integer)
2336 switch(rsurface.texture->offsetmapping)
2338 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2339 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2340 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2341 case OFFSETMAPPING_OFF: break;
2344 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2345 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2347 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2348 permutation |= SHADERPERMUTATION_GLOW;
2349 if (r_refdef.fogenabled)
2350 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2351 if (rsurface.texture->colormapping)
2352 permutation |= SHADERPERMUTATION_COLORMAPPING;
2353 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2355 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2356 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2358 if (r_shadow_shadowmapsampler)
2359 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2360 if (r_shadow_shadowmappcf > 1)
2361 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2362 else if (r_shadow_shadowmappcf)
2363 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2365 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2366 permutation |= SHADERPERMUTATION_REFLECTION;
2367 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2368 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2369 if (rsurface.texture->reflectmasktexture)
2370 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2371 if (FAKELIGHT_ENABLED)
2373 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2374 mode = SHADERMODE_FAKELIGHT;
2375 permutation |= SHADERPERMUTATION_DIFFUSE;
2376 if (specularscale > 0)
2377 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2379 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2381 // deluxemapping (light direction texture)
2382 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2383 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2385 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2386 permutation |= SHADERPERMUTATION_DIFFUSE;
2387 if (specularscale > 0)
2388 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2390 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2392 // fake deluxemapping (uniform light direction in tangentspace)
2393 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2394 permutation |= SHADERPERMUTATION_DIFFUSE;
2395 if (specularscale > 0)
2396 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2398 else if (rsurface.uselightmaptexture)
2400 // ordinary lightmapping (q1bsp, q3bsp)
2401 mode = SHADERMODE_LIGHTMAP;
2405 // ordinary vertex coloring (q3bsp)
2406 mode = SHADERMODE_VERTEXCOLOR;
2408 if (r_shadow_bouncegridtexture)
2410 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2411 if (r_shadow_bouncegriddirectional)
2412 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2414 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2415 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2417 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2418 colormod = dummy_colormod;
2419 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2420 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2421 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2422 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2423 switch(vid.renderpath)
2425 case RENDERPATH_D3D9:
2427 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);
2428 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2429 R_SetupShader_SetPermutationHLSL(mode, permutation);
2430 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2431 if (mode == SHADERMODE_LIGHTSOURCE)
2433 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2434 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2438 if (mode == SHADERMODE_LIGHTDIRECTION)
2440 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2443 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2444 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2445 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2446 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2447 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2449 if (mode == SHADERMODE_LIGHTSOURCE)
2451 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2452 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2453 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2454 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2455 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2457 // additive passes are only darkened by fog, not tinted
2458 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2459 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2463 if (mode == SHADERMODE_FLATCOLOR)
2465 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2467 else if (mode == SHADERMODE_LIGHTDIRECTION)
2469 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]);
2470 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2471 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);
2472 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);
2473 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2474 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2475 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2479 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2480 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2481 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);
2482 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);
2483 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2485 // additive passes are only darkened by fog, not tinted
2486 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2487 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2489 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2490 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);
2491 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2492 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2493 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2494 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2495 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2496 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2497 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2498 if (mode == SHADERMODE_WATER)
2499 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2501 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2502 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2503 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2504 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));
2505 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2506 if (rsurface.texture->pantstexture)
2507 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2509 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2510 if (rsurface.texture->shirttexture)
2511 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2513 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2514 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2515 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2516 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2517 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2518 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));
2519 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2520 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2522 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2523 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2524 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2525 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2526 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2527 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2528 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2529 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2530 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2531 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2532 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2533 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2534 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2535 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2536 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2537 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2538 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2539 if (rsurfacepass == RSURFPASS_BACKGROUND)
2541 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2542 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2543 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2547 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2549 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2550 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2551 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2552 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2553 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2555 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2556 if (rsurface.rtlight)
2558 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2559 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2564 case RENDERPATH_D3D10:
2565 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2567 case RENDERPATH_D3D11:
2568 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2570 case RENDERPATH_GL20:
2571 case RENDERPATH_GLES2:
2572 if (!vid.useinterleavedarrays)
2574 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);
2575 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2576 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2577 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2578 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2579 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2580 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2581 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2585 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);
2586 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2588 R_SetupShader_SetPermutationGLSL(mode, permutation);
2589 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2590 if (mode == SHADERMODE_LIGHTSOURCE)
2592 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2593 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2594 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2595 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2596 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2597 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);
2599 // additive passes are only darkened by fog, not tinted
2600 if (r_glsl_permutation->loc_FogColor >= 0)
2601 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2602 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2606 if (mode == SHADERMODE_FLATCOLOR)
2608 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2610 else if (mode == SHADERMODE_LIGHTDIRECTION)
2612 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]);
2613 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]);
2614 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);
2615 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);
2616 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);
2617 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]);
2618 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]);
2622 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]);
2623 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]);
2624 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);
2625 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);
2626 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);
2628 // additive passes are only darkened by fog, not tinted
2629 if (r_glsl_permutation->loc_FogColor >= 0)
2631 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2632 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2634 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2636 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);
2637 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]);
2638 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]);
2639 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]);
2640 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]);
2641 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2642 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2643 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2644 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]);
2646 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2647 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2648 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2649 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]);
2650 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]);
2652 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2653 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));
2654 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2655 if (r_glsl_permutation->loc_Color_Pants >= 0)
2657 if (rsurface.texture->pantstexture)
2658 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2660 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2662 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2664 if (rsurface.texture->shirttexture)
2665 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2667 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2669 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]);
2670 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2671 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2672 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2673 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));
2674 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]);
2675 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2676 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);}
2677 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2679 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2680 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2681 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2682 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2683 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2684 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2685 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2686 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2687 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2688 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2689 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2690 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2691 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2692 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2693 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);
2694 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2695 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2696 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2697 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2698 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2699 if (rsurfacepass == RSURFPASS_BACKGROUND)
2701 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);
2702 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);
2703 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);
2707 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);
2709 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2710 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2711 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2712 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2713 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2715 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
2716 if (rsurface.rtlight)
2718 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2719 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2722 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2725 case RENDERPATH_GL13:
2726 case RENDERPATH_GL11:
2728 case RENDERPATH_SOFT:
2729 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);
2730 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2731 R_SetupShader_SetPermutationSoft(mode, permutation);
2732 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2733 if (mode == SHADERMODE_LIGHTSOURCE)
2735 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2736 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2737 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2738 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2739 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2740 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2742 // additive passes are only darkened by fog, not tinted
2743 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2744 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2748 if (mode == SHADERMODE_FLATCOLOR)
2750 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2752 else if (mode == SHADERMODE_LIGHTDIRECTION)
2754 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]);
2755 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2756 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);
2757 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);
2758 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2759 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]);
2760 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2764 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2765 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2766 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);
2767 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);
2768 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2770 // additive passes are only darkened by fog, not tinted
2771 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2772 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2774 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2775 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);
2776 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2777 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2778 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]);
2779 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]);
2780 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2781 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2782 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2783 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2785 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2786 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2787 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2788 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2789 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]);
2791 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2792 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));
2793 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2794 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2796 if (rsurface.texture->pantstexture)
2797 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2799 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2801 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2803 if (rsurface.texture->shirttexture)
2804 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2806 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2808 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2809 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2810 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2811 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2812 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));
2813 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2814 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2816 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2817 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2818 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2819 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2820 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2821 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2822 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2823 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2824 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2825 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2826 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2827 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2828 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2829 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2830 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2831 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2832 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2833 if (rsurfacepass == RSURFPASS_BACKGROUND)
2835 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2836 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2837 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2841 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2843 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2844 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2845 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2846 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2847 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2849 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2850 if (rsurface.rtlight)
2852 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2853 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2860 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2862 // select a permutation of the lighting shader appropriate to this
2863 // combination of texture, entity, light source, and fogging, only use the
2864 // minimum features necessary to avoid wasting rendering time in the
2865 // fragment shader on features that are not being used
2866 unsigned int permutation = 0;
2867 unsigned int mode = 0;
2868 const float *lightcolorbase = rtlight->currentcolor;
2869 float ambientscale = rtlight->ambientscale;
2870 float diffusescale = rtlight->diffusescale;
2871 float specularscale = rtlight->specularscale;
2872 // this is the location of the light in view space
2873 vec3_t viewlightorigin;
2874 // this transforms from view space (camera) to light space (cubemap)
2875 matrix4x4_t viewtolight;
2876 matrix4x4_t lighttoview;
2877 float viewtolight16f[16];
2878 float range = 1.0f / r_shadow_deferred_8bitrange.value;
2880 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2881 if (rtlight->currentcubemap != r_texture_whitecube)
2882 permutation |= SHADERPERMUTATION_CUBEFILTER;
2883 if (diffusescale > 0)
2884 permutation |= SHADERPERMUTATION_DIFFUSE;
2885 if (specularscale > 0 && r_shadow_gloss.integer > 0)
2886 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2887 if (r_shadow_usingshadowmap2d)
2889 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2890 if (r_shadow_shadowmapvsdct)
2891 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2893 if (r_shadow_shadowmapsampler)
2894 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2895 if (r_shadow_shadowmappcf > 1)
2896 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2897 else if (r_shadow_shadowmappcf)
2898 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2900 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2901 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2902 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2903 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2904 switch(vid.renderpath)
2906 case RENDERPATH_D3D9:
2908 R_SetupShader_SetPermutationHLSL(mode, permutation);
2909 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2910 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2911 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2912 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2913 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2914 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2915 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2916 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2917 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2918 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2920 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2921 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
2922 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2923 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2924 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
2925 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2928 case RENDERPATH_D3D10:
2929 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2931 case RENDERPATH_D3D11:
2932 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2934 case RENDERPATH_GL20:
2935 case RENDERPATH_GLES2:
2936 R_SetupShader_SetPermutationGLSL(mode, permutation);
2937 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2938 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
2939 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);
2940 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);
2941 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);
2942 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]);
2943 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]);
2944 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));
2945 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]);
2946 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
2948 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2949 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2950 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2951 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2952 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
2953 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2955 case RENDERPATH_GL13:
2956 case RENDERPATH_GL11:
2958 case RENDERPATH_SOFT:
2959 R_SetupShader_SetPermutationGLSL(mode, permutation);
2960 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2961 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
2962 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2963 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2964 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2965 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2966 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]);
2967 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));
2968 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2969 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2971 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2972 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2973 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2974 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2975 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
2976 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2981 #define SKINFRAME_HASH 1024
2985 int loadsequence; // incremented each level change
2986 memexpandablearray_t array;
2987 skinframe_t *hash[SKINFRAME_HASH];
2990 r_skinframe_t r_skinframe;
2992 void R_SkinFrame_PrepareForPurge(void)
2994 r_skinframe.loadsequence++;
2995 // wrap it without hitting zero
2996 if (r_skinframe.loadsequence >= 200)
2997 r_skinframe.loadsequence = 1;
3000 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3004 // mark the skinframe as used for the purging code
3005 skinframe->loadsequence = r_skinframe.loadsequence;
3008 void R_SkinFrame_Purge(void)
3012 for (i = 0;i < SKINFRAME_HASH;i++)
3014 for (s = r_skinframe.hash[i];s;s = s->next)
3016 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3018 if (s->merged == s->base)
3020 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3021 R_PurgeTexture(s->stain );s->stain = NULL;
3022 R_PurgeTexture(s->merged);s->merged = NULL;
3023 R_PurgeTexture(s->base );s->base = NULL;
3024 R_PurgeTexture(s->pants );s->pants = NULL;
3025 R_PurgeTexture(s->shirt );s->shirt = NULL;
3026 R_PurgeTexture(s->nmap );s->nmap = NULL;
3027 R_PurgeTexture(s->gloss );s->gloss = NULL;
3028 R_PurgeTexture(s->glow );s->glow = NULL;
3029 R_PurgeTexture(s->fog );s->fog = NULL;
3030 R_PurgeTexture(s->reflect);s->reflect = NULL;
3031 s->loadsequence = 0;
3037 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3039 char basename[MAX_QPATH];
3041 Image_StripImageExtension(name, basename, sizeof(basename));
3043 if( last == NULL ) {
3045 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3046 item = r_skinframe.hash[hashindex];
3051 // linearly search through the hash bucket
3052 for( ; item ; item = item->next ) {
3053 if( !strcmp( item->basename, basename ) ) {
3060 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3064 char basename[MAX_QPATH];
3066 Image_StripImageExtension(name, basename, sizeof(basename));
3068 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3069 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3070 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3074 rtexture_t *dyntexture;
3075 // check whether its a dynamic texture
3076 dyntexture = CL_GetDynTexture( basename );
3077 if (!add && !dyntexture)
3079 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3080 memset(item, 0, sizeof(*item));
3081 strlcpy(item->basename, basename, sizeof(item->basename));
3082 item->base = dyntexture; // either NULL or dyntexture handle
3083 item->textureflags = textureflags;
3084 item->comparewidth = comparewidth;
3085 item->compareheight = compareheight;
3086 item->comparecrc = comparecrc;
3087 item->next = r_skinframe.hash[hashindex];
3088 r_skinframe.hash[hashindex] = item;
3090 else if( item->base == NULL )
3092 rtexture_t *dyntexture;
3093 // check whether its a dynamic texture
3094 // 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]
3095 dyntexture = CL_GetDynTexture( basename );
3096 item->base = dyntexture; // either NULL or dyntexture handle
3099 R_SkinFrame_MarkUsed(item);
3103 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3105 unsigned long long avgcolor[5], wsum; \
3113 for(pix = 0; pix < cnt; ++pix) \
3116 for(comp = 0; comp < 3; ++comp) \
3118 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3121 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3123 for(comp = 0; comp < 3; ++comp) \
3124 avgcolor[comp] += getpixel * w; \
3127 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3128 avgcolor[4] += getpixel; \
3130 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3132 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3133 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3134 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3135 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3138 extern cvar_t gl_picmip;
3139 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3142 unsigned char *pixels;
3143 unsigned char *bumppixels;
3144 unsigned char *basepixels = NULL;
3145 int basepixels_width = 0;
3146 int basepixels_height = 0;
3147 skinframe_t *skinframe;
3148 rtexture_t *ddsbase = NULL;
3149 qboolean ddshasalpha = false;
3150 float ddsavgcolor[4];
3151 char basename[MAX_QPATH];
3152 int miplevel = R_PicmipForFlags(textureflags);
3153 int savemiplevel = miplevel;
3156 if (cls.state == ca_dedicated)
3159 // return an existing skinframe if already loaded
3160 // if loading of the first image fails, don't make a new skinframe as it
3161 // would cause all future lookups of this to be missing
3162 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3163 if (skinframe && skinframe->base)
3166 Image_StripImageExtension(name, basename, sizeof(basename));
3168 // check for DDS texture file first
3169 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3171 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
3172 if (basepixels == NULL)
3176 // FIXME handle miplevel
3178 if (developer_loading.integer)
3179 Con_Printf("loading skin \"%s\"\n", name);
3181 // we've got some pixels to store, so really allocate this new texture now
3183 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3184 skinframe->stain = NULL;
3185 skinframe->merged = NULL;
3186 skinframe->base = NULL;
3187 skinframe->pants = NULL;
3188 skinframe->shirt = NULL;
3189 skinframe->nmap = NULL;
3190 skinframe->gloss = NULL;
3191 skinframe->glow = NULL;
3192 skinframe->fog = NULL;
3193 skinframe->reflect = NULL;
3194 skinframe->hasalpha = false;
3198 skinframe->base = ddsbase;
3199 skinframe->hasalpha = ddshasalpha;
3200 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3201 if (r_loadfog && skinframe->hasalpha)
3202 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3203 //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]);
3207 basepixels_width = image_width;
3208 basepixels_height = image_height;
3209 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);
3210 if (textureflags & TEXF_ALPHA)
3212 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3214 if (basepixels[j] < 255)
3216 skinframe->hasalpha = true;
3220 if (r_loadfog && skinframe->hasalpha)
3222 // has transparent pixels
3223 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3224 for (j = 0;j < image_width * image_height * 4;j += 4)
3229 pixels[j+3] = basepixels[j+3];
3231 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);
3235 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3236 //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]);
3237 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3238 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
3239 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3240 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
3245 mymiplevel = savemiplevel;
3246 if (r_loadnormalmap)
3247 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);
3248 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3250 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3251 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3252 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3253 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3256 // _norm is the name used by tenebrae and has been adopted as standard
3257 if (r_loadnormalmap && skinframe->nmap == NULL)
3259 mymiplevel = savemiplevel;
3260 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3262 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);
3266 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3268 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3269 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3270 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);
3272 Mem_Free(bumppixels);
3274 else if (r_shadow_bumpscale_basetexture.value > 0)
3276 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3277 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3278 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);
3281 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3282 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
3285 // _luma is supported only for tenebrae compatibility
3286 // _glow is the preferred name
3287 mymiplevel = savemiplevel;
3288 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))))
3290 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);
3291 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3292 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
3293 Mem_Free(pixels);pixels = NULL;
3296 mymiplevel = savemiplevel;
3297 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3299 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);
3300 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3301 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
3306 mymiplevel = savemiplevel;
3307 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3309 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);
3310 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3311 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
3316 mymiplevel = savemiplevel;
3317 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3319 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);
3320 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3321 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
3326 mymiplevel = savemiplevel;
3327 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3329 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);
3330 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3331 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
3337 Mem_Free(basepixels);
3342 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3343 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
3346 unsigned char *temp1, *temp2;
3347 skinframe_t *skinframe;
3349 if (cls.state == ca_dedicated)
3352 // if already loaded just return it, otherwise make a new skinframe
3353 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3354 if (skinframe && skinframe->base)
3357 skinframe->stain = NULL;
3358 skinframe->merged = NULL;
3359 skinframe->base = NULL;
3360 skinframe->pants = NULL;
3361 skinframe->shirt = NULL;
3362 skinframe->nmap = NULL;
3363 skinframe->gloss = NULL;
3364 skinframe->glow = NULL;
3365 skinframe->fog = NULL;
3366 skinframe->reflect = NULL;
3367 skinframe->hasalpha = false;
3369 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3373 if (developer_loading.integer)
3374 Con_Printf("loading 32bit skin \"%s\"\n", name);
3376 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3378 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3379 temp2 = temp1 + width * height * 4;
3380 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3381 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);
3384 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
3385 if (textureflags & TEXF_ALPHA)
3387 for (i = 3;i < width * height * 4;i += 4)
3389 if (skindata[i] < 255)
3391 skinframe->hasalpha = true;
3395 if (r_loadfog && skinframe->hasalpha)
3397 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3398 memcpy(fogpixels, skindata, width * height * 4);
3399 for (i = 0;i < width * height * 4;i += 4)
3400 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3401 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3402 Mem_Free(fogpixels);
3406 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3407 //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]);
3412 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3416 skinframe_t *skinframe;
3418 if (cls.state == ca_dedicated)
3421 // if already loaded just return it, otherwise make a new skinframe
3422 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3423 if (skinframe && skinframe->base)
3426 skinframe->stain = NULL;
3427 skinframe->merged = NULL;
3428 skinframe->base = NULL;
3429 skinframe->pants = NULL;
3430 skinframe->shirt = NULL;
3431 skinframe->nmap = NULL;
3432 skinframe->gloss = NULL;
3433 skinframe->glow = NULL;
3434 skinframe->fog = NULL;
3435 skinframe->reflect = NULL;
3436 skinframe->hasalpha = false;
3438 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3442 if (developer_loading.integer)
3443 Con_Printf("loading quake skin \"%s\"\n", name);
3445 // 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)
3446 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3447 memcpy(skinframe->qpixels, skindata, width*height);
3448 skinframe->qwidth = width;
3449 skinframe->qheight = height;
3452 for (i = 0;i < width * height;i++)
3453 featuresmask |= palette_featureflags[skindata[i]];
3455 skinframe->hasalpha = false;
3456 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3457 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3458 skinframe->qgeneratemerged = true;
3459 skinframe->qgeneratebase = skinframe->qhascolormapping;
3460 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3462 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3463 //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]);
3468 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3472 unsigned char *skindata;
3474 if (!skinframe->qpixels)
3477 if (!skinframe->qhascolormapping)
3478 colormapped = false;
3482 if (!skinframe->qgeneratebase)
3487 if (!skinframe->qgeneratemerged)
3491 width = skinframe->qwidth;
3492 height = skinframe->qheight;
3493 skindata = skinframe->qpixels;
3495 if (skinframe->qgeneratenmap)
3497 unsigned char *temp1, *temp2;
3498 skinframe->qgeneratenmap = false;
3499 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3500 temp2 = temp1 + width * height * 4;
3501 // use either a custom palette or the quake palette
3502 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3503 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3504 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);
3508 if (skinframe->qgenerateglow)
3510 skinframe->qgenerateglow = false;
3511 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3516 skinframe->qgeneratebase = false;
3517 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);
3518 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3519 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3523 skinframe->qgeneratemerged = false;
3524 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);
3527 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3529 Mem_Free(skinframe->qpixels);
3530 skinframe->qpixels = NULL;
3534 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)
3537 skinframe_t *skinframe;
3539 if (cls.state == ca_dedicated)
3542 // if already loaded just return it, otherwise make a new skinframe
3543 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3544 if (skinframe && skinframe->base)
3547 skinframe->stain = NULL;
3548 skinframe->merged = NULL;
3549 skinframe->base = NULL;
3550 skinframe->pants = NULL;
3551 skinframe->shirt = NULL;
3552 skinframe->nmap = NULL;
3553 skinframe->gloss = NULL;
3554 skinframe->glow = NULL;
3555 skinframe->fog = NULL;
3556 skinframe->reflect = NULL;
3557 skinframe->hasalpha = false;
3559 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3563 if (developer_loading.integer)
3564 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3566 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3567 if (textureflags & TEXF_ALPHA)
3569 for (i = 0;i < width * height;i++)
3571 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3573 skinframe->hasalpha = true;
3577 if (r_loadfog && skinframe->hasalpha)
3578 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3581 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3582 //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]);
3587 skinframe_t *R_SkinFrame_LoadMissing(void)
3589 skinframe_t *skinframe;
3591 if (cls.state == ca_dedicated)
3594 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3595 skinframe->stain = NULL;
3596 skinframe->merged = NULL;
3597 skinframe->base = NULL;
3598 skinframe->pants = NULL;
3599 skinframe->shirt = NULL;
3600 skinframe->nmap = NULL;
3601 skinframe->gloss = NULL;
3602 skinframe->glow = NULL;
3603 skinframe->fog = NULL;
3604 skinframe->reflect = NULL;
3605 skinframe->hasalpha = false;
3607 skinframe->avgcolor[0] = rand() / RAND_MAX;
3608 skinframe->avgcolor[1] = rand() / RAND_MAX;
3609 skinframe->avgcolor[2] = rand() / RAND_MAX;
3610 skinframe->avgcolor[3] = 1;
3615 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3616 typedef struct suffixinfo_s
3619 qboolean flipx, flipy, flipdiagonal;
3622 static suffixinfo_t suffix[3][6] =
3625 {"px", false, false, false},
3626 {"nx", false, false, false},
3627 {"py", false, false, false},
3628 {"ny", false, false, false},
3629 {"pz", false, false, false},
3630 {"nz", false, false, false}
3633 {"posx", false, false, false},
3634 {"negx", false, false, false},
3635 {"posy", false, false, false},
3636 {"negy", false, false, false},
3637 {"posz", false, false, false},
3638 {"negz", false, false, false}
3641 {"rt", true, false, true},
3642 {"lf", false, true, true},
3643 {"ft", true, true, false},
3644 {"bk", false, false, false},
3645 {"up", true, false, true},
3646 {"dn", true, false, true}
3650 static int componentorder[4] = {0, 1, 2, 3};
3652 rtexture_t *R_LoadCubemap(const char *basename)
3654 int i, j, cubemapsize;
3655 unsigned char *cubemappixels, *image_buffer;
3656 rtexture_t *cubemaptexture;
3658 // must start 0 so the first loadimagepixels has no requested width/height
3660 cubemappixels = NULL;
3661 cubemaptexture = NULL;
3662 // keep trying different suffix groups (posx, px, rt) until one loads
3663 for (j = 0;j < 3 && !cubemappixels;j++)
3665 // load the 6 images in the suffix group
3666 for (i = 0;i < 6;i++)
3668 // generate an image name based on the base and and suffix
3669 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3671 if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
3673 // an image loaded, make sure width and height are equal
3674 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3676 // if this is the first image to load successfully, allocate the cubemap memory
3677 if (!cubemappixels && image_width >= 1)
3679 cubemapsize = image_width;
3680 // note this clears to black, so unavailable sides are black
3681 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3683 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3685 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);
3688 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3690 Mem_Free(image_buffer);
3694 // if a cubemap loaded, upload it
3697 if (developer_loading.integer)
3698 Con_Printf("loading cubemap \"%s\"\n", basename);
3700 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3701 Mem_Free(cubemappixels);
3705 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3706 if (developer_loading.integer)
3708 Con_Printf("(tried tried images ");
3709 for (j = 0;j < 3;j++)
3710 for (i = 0;i < 6;i++)
3711 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3712 Con_Print(" and was unable to find any of them).\n");
3715 return cubemaptexture;
3718 rtexture_t *R_GetCubemap(const char *basename)
3721 for (i = 0;i < r_texture_numcubemaps;i++)
3722 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3723 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3724 if (i >= MAX_CUBEMAPS)
3725 return r_texture_whitecube;
3726 r_texture_numcubemaps++;
3727 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3728 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3729 return r_texture_cubemaps[i].texture;
3732 void R_FreeCubemaps(void)
3735 for (i = 0;i < r_texture_numcubemaps;i++)
3737 if (developer_loading.integer)
3738 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3739 if (r_texture_cubemaps[i].texture)
3740 R_FreeTexture(r_texture_cubemaps[i].texture);
3742 r_texture_numcubemaps = 0;
3745 void R_Main_FreeViewCache(void)
3747 if (r_refdef.viewcache.entityvisible)
3748 Mem_Free(r_refdef.viewcache.entityvisible);
3749 if (r_refdef.viewcache.world_pvsbits)
3750 Mem_Free(r_refdef.viewcache.world_pvsbits);
3751 if (r_refdef.viewcache.world_leafvisible)
3752 Mem_Free(r_refdef.viewcache.world_leafvisible);
3753 if (r_refdef.viewcache.world_surfacevisible)
3754 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3755 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3758 void R_Main_ResizeViewCache(void)
3760 int numentities = r_refdef.scene.numentities;
3761 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3762 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3763 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3764 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3765 if (r_refdef.viewcache.maxentities < numentities)
3767 r_refdef.viewcache.maxentities = numentities;
3768 if (r_refdef.viewcache.entityvisible)
3769 Mem_Free(r_refdef.viewcache.entityvisible);
3770 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3772 if (r_refdef.viewcache.world_numclusters != numclusters)
3774 r_refdef.viewcache.world_numclusters = numclusters;
3775 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3776 if (r_refdef.viewcache.world_pvsbits)
3777 Mem_Free(r_refdef.viewcache.world_pvsbits);
3778 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3780 if (r_refdef.viewcache.world_numleafs != numleafs)
3782 r_refdef.viewcache.world_numleafs = numleafs;
3783 if (r_refdef.viewcache.world_leafvisible)
3784 Mem_Free(r_refdef.viewcache.world_leafvisible);
3785 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3787 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3789 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3790 if (r_refdef.viewcache.world_surfacevisible)
3791 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3792 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3796 extern rtexture_t *loadingscreentexture;
3797 void gl_main_start(void)
3799 loadingscreentexture = NULL;
3800 r_texture_blanknormalmap = NULL;
3801 r_texture_white = NULL;
3802 r_texture_grey128 = NULL;
3803 r_texture_black = NULL;
3804 r_texture_whitecube = NULL;
3805 r_texture_normalizationcube = NULL;
3806 r_texture_fogattenuation = NULL;
3807 r_texture_fogheighttexture = NULL;
3808 r_texture_gammaramps = NULL;
3809 r_texture_numcubemaps = 0;
3811 r_loaddds = r_texture_dds_load.integer != 0;
3812 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3814 switch(vid.renderpath)
3816 case RENDERPATH_GL20:
3817 case RENDERPATH_D3D9:
3818 case RENDERPATH_D3D10:
3819 case RENDERPATH_D3D11:
3820 case RENDERPATH_SOFT:
3821 case RENDERPATH_GLES2:
3822 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3823 Cvar_SetValueQuick(&gl_combine, 1);
3824 Cvar_SetValueQuick(&r_glsl, 1);
3825 r_loadnormalmap = true;
3829 case RENDERPATH_GL13:
3830 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3831 Cvar_SetValueQuick(&gl_combine, 1);
3832 Cvar_SetValueQuick(&r_glsl, 0);
3833 r_loadnormalmap = false;
3834 r_loadgloss = false;
3837 case RENDERPATH_GL11:
3838 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3839 Cvar_SetValueQuick(&gl_combine, 0);
3840 Cvar_SetValueQuick(&r_glsl, 0);
3841 r_loadnormalmap = false;
3842 r_loadgloss = false;
3848 R_FrameData_Reset();
3852 memset(r_queries, 0, sizeof(r_queries));
3854 r_qwskincache = NULL;
3855 r_qwskincache_size = 0;
3857 // due to caching of texture_t references, the collision cache must be reset
3858 Collision_Cache_Reset(true);
3860 // set up r_skinframe loading system for textures
3861 memset(&r_skinframe, 0, sizeof(r_skinframe));
3862 r_skinframe.loadsequence = 1;
3863 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3865 r_main_texturepool = R_AllocTexturePool();
3866 R_BuildBlankTextures();
3868 if (vid.support.arb_texture_cube_map)
3871 R_BuildNormalizationCube();
3873 r_texture_fogattenuation = NULL;
3874 r_texture_fogheighttexture = NULL;
3875 r_texture_gammaramps = NULL;
3876 //r_texture_fogintensity = NULL;
3877 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3878 memset(&r_waterstate, 0, sizeof(r_waterstate));
3879 r_glsl_permutation = NULL;
3880 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3881 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3882 glslshaderstring = NULL;
3884 r_hlsl_permutation = NULL;
3885 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3886 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3888 hlslshaderstring = NULL;
3889 memset(&r_svbsp, 0, sizeof (r_svbsp));
3891 r_refdef.fogmasktable_density = 0;
3894 void gl_main_shutdown(void)
3897 R_FrameData_Reset();
3899 R_Main_FreeViewCache();
3901 switch(vid.renderpath)
3903 case RENDERPATH_GL11:
3904 case RENDERPATH_GL13:
3905 case RENDERPATH_GL20:
3906 case RENDERPATH_GLES2:
3908 qglDeleteQueriesARB(r_maxqueries, r_queries);
3910 case RENDERPATH_D3D9:
3911 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3913 case RENDERPATH_D3D10:
3914 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3916 case RENDERPATH_D3D11:
3917 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3919 case RENDERPATH_SOFT:
3925 memset(r_queries, 0, sizeof(r_queries));
3927 r_qwskincache = NULL;
3928 r_qwskincache_size = 0;
3930 // clear out the r_skinframe state
3931 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3932 memset(&r_skinframe, 0, sizeof(r_skinframe));
3935 Mem_Free(r_svbsp.nodes);
3936 memset(&r_svbsp, 0, sizeof (r_svbsp));
3937 R_FreeTexturePool(&r_main_texturepool);
3938 loadingscreentexture = NULL;
3939 r_texture_blanknormalmap = NULL;
3940 r_texture_white = NULL;
3941 r_texture_grey128 = NULL;
3942 r_texture_black = NULL;
3943 r_texture_whitecube = NULL;
3944 r_texture_normalizationcube = NULL;
3945 r_texture_fogattenuation = NULL;
3946 r_texture_fogheighttexture = NULL;
3947 r_texture_gammaramps = NULL;
3948 r_texture_numcubemaps = 0;
3949 //r_texture_fogintensity = NULL;
3950 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3951 memset(&r_waterstate, 0, sizeof(r_waterstate));
3954 r_glsl_permutation = NULL;
3955 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3956 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3957 glslshaderstring = NULL;
3959 r_hlsl_permutation = NULL;
3960 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3961 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3963 hlslshaderstring = NULL;
3966 extern void CL_ParseEntityLump(char *entitystring);
3967 void gl_main_newmap(void)
3969 // FIXME: move this code to client
3970 char *entities, entname[MAX_QPATH];
3972 Mem_Free(r_qwskincache);
3973 r_qwskincache = NULL;
3974 r_qwskincache_size = 0;
3977 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
3978 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
3980 CL_ParseEntityLump(entities);
3984 if (cl.worldmodel->brush.entities)
3985 CL_ParseEntityLump(cl.worldmodel->brush.entities);
3987 R_Main_FreeViewCache();
3989 R_FrameData_Reset();
3992 void GL_Main_Init(void)
3994 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
3996 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
3997 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
3998 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
3999 if (gamemode == GAME_NEHAHRA)
4001 Cvar_RegisterVariable (&gl_fogenable);
4002 Cvar_RegisterVariable (&gl_fogdensity);
4003 Cvar_RegisterVariable (&gl_fogred);
4004 Cvar_RegisterVariable (&gl_foggreen);
4005 Cvar_RegisterVariable (&gl_fogblue);
4006 Cvar_RegisterVariable (&gl_fogstart);
4007 Cvar_RegisterVariable (&gl_fogend);
4008 Cvar_RegisterVariable (&gl_skyclip);
4010 Cvar_RegisterVariable(&r_motionblur);
4011 Cvar_RegisterVariable(&r_motionblur_maxblur);
4012 Cvar_RegisterVariable(&r_motionblur_bmin);
4013 Cvar_RegisterVariable(&r_motionblur_vmin);
4014 Cvar_RegisterVariable(&r_motionblur_vmax);
4015 Cvar_RegisterVariable(&r_motionblur_vcoeff);
4016 Cvar_RegisterVariable(&r_motionblur_randomize);
4017 Cvar_RegisterVariable(&r_damageblur);
4018 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4019 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4020 Cvar_RegisterVariable(&r_equalize_entities_by);
4021 Cvar_RegisterVariable(&r_equalize_entities_to);
4022 Cvar_RegisterVariable(&r_depthfirst);
4023 Cvar_RegisterVariable(&r_useinfinitefarclip);
4024 Cvar_RegisterVariable(&r_farclip_base);
4025 Cvar_RegisterVariable(&r_farclip_world);
4026 Cvar_RegisterVariable(&r_nearclip);
4027 Cvar_RegisterVariable(&r_showbboxes);
4028 Cvar_RegisterVariable(&r_showsurfaces);
4029 Cvar_RegisterVariable(&r_showtris);
4030 Cvar_RegisterVariable(&r_shownormals);
4031 Cvar_RegisterVariable(&r_showlighting);
4032 Cvar_RegisterVariable(&r_showshadowvolumes);
4033 Cvar_RegisterVariable(&r_showcollisionbrushes);
4034 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4035 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4036 Cvar_RegisterVariable(&r_showdisabledepthtest);
4037 Cvar_RegisterVariable(&r_drawportals);
4038 Cvar_RegisterVariable(&r_drawentities);
4039 Cvar_RegisterVariable(&r_draw2d);
4040 Cvar_RegisterVariable(&r_drawworld);
4041 Cvar_RegisterVariable(&r_cullentities_trace);
4042 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4043 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4044 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4045 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4046 Cvar_RegisterVariable(&r_drawviewmodel);
4047 Cvar_RegisterVariable(&r_drawexteriormodel);
4048 Cvar_RegisterVariable(&r_speeds);
4049 Cvar_RegisterVariable(&r_fullbrights);
4050 Cvar_RegisterVariable(&r_wateralpha);
4051 Cvar_RegisterVariable(&r_dynamic);
4052 Cvar_RegisterVariable(&r_fakelight);
4053 Cvar_RegisterVariable(&r_fakelight_intensity);
4054 Cvar_RegisterVariable(&r_fullbright);
4055 Cvar_RegisterVariable(&r_shadows);
4056 Cvar_RegisterVariable(&r_shadows_darken);
4057 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4058 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4059 Cvar_RegisterVariable(&r_shadows_throwdistance);
4060 Cvar_RegisterVariable(&r_shadows_throwdirection);
4061 Cvar_RegisterVariable(&r_shadows_focus);
4062 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4063 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4064 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4065 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4066 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4067 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4068 Cvar_RegisterVariable(&r_fog_exp2);
4069 Cvar_RegisterVariable(&r_fog_clear);
4070 Cvar_RegisterVariable(&r_drawfog);
4071 Cvar_RegisterVariable(&r_transparentdepthmasking);
4072 Cvar_RegisterVariable(&r_texture_dds_load);
4073 Cvar_RegisterVariable(&r_texture_dds_save);
4074 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
4075 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
4076 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
4077 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
4078 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
4079 Cvar_RegisterVariable(&r_textureunits);
4080 Cvar_RegisterVariable(&gl_combine);
4081 Cvar_RegisterVariable(&r_viewfbo);
4082 Cvar_RegisterVariable(&r_viewscale);
4083 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4084 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4085 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4086 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4087 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4088 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4089 Cvar_RegisterVariable(&r_glsl);
4090 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4091 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4092 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4093 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4094 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4095 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4096 Cvar_RegisterVariable(&r_glsl_postprocess);
4097 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4098 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4099 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4100 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4101 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4102 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4103 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4104 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4106 Cvar_RegisterVariable(&r_water);
4107 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4108 Cvar_RegisterVariable(&r_water_clippingplanebias);
4109 Cvar_RegisterVariable(&r_water_refractdistort);
4110 Cvar_RegisterVariable(&r_water_reflectdistort);
4111 Cvar_RegisterVariable(&r_water_scissormode);
4112 Cvar_RegisterVariable(&r_lerpsprites);
4113 Cvar_RegisterVariable(&r_lerpmodels);
4114 Cvar_RegisterVariable(&r_lerplightstyles);
4115 Cvar_RegisterVariable(&r_waterscroll);
4116 Cvar_RegisterVariable(&r_bloom);
4117 Cvar_RegisterVariable(&r_bloom_colorscale);
4118 Cvar_RegisterVariable(&r_bloom_brighten);
4119 Cvar_RegisterVariable(&r_bloom_blur);
4120 Cvar_RegisterVariable(&r_bloom_resolution);
4121 Cvar_RegisterVariable(&r_bloom_colorexponent);
4122 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4123 Cvar_RegisterVariable(&r_hdr);
4124 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4125 Cvar_RegisterVariable(&r_hdr_glowintensity);
4126 Cvar_RegisterVariable(&r_hdr_range);
4127 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4128 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4129 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4130 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4131 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4132 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4133 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4134 Cvar_RegisterVariable(&developer_texturelogging);
4135 Cvar_RegisterVariable(&gl_lightmaps);
4136 Cvar_RegisterVariable(&r_test);
4137 Cvar_RegisterVariable(&r_glsl_saturation);
4138 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4139 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4140 Cvar_RegisterVariable(&r_framedatasize);
4141 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4142 Cvar_SetValue("r_fullbrights", 0);
4143 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4145 Cvar_RegisterVariable(&r_track_sprites);
4146 Cvar_RegisterVariable(&r_track_sprites_flags);
4147 Cvar_RegisterVariable(&r_track_sprites_scalew);
4148 Cvar_RegisterVariable(&r_track_sprites_scaleh);
4149 Cvar_RegisterVariable(&r_overheadsprites_perspective);
4150 Cvar_RegisterVariable(&r_overheadsprites_pushback);
4151 Cvar_RegisterVariable(&r_overheadsprites_scalex);
4152 Cvar_RegisterVariable(&r_overheadsprites_scaley);
4155 extern void R_Textures_Init(void);
4156 extern void GL_Draw_Init(void);
4157 extern void GL_Main_Init(void);
4158 extern void R_Shadow_Init(void);
4159 extern void R_Sky_Init(void);
4160 extern void GL_Surf_Init(void);
4161 extern void R_Particles_Init(void);
4162 extern void R_Explosion_Init(void);
4163 extern void gl_backend_init(void);
4164 extern void Sbar_Init(void);
4165 extern void R_LightningBeams_Init(void);
4166 extern void Mod_RenderInit(void);
4167 extern void Font_Init(void);
4169 void Render_Init(void)
4182 R_LightningBeams_Init();
4191 extern char *ENGINE_EXTENSIONS;
4194 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4195 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4196 gl_version = (const char *)qglGetString(GL_VERSION);
4197 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4201 if (!gl_platformextensions)
4202 gl_platformextensions = "";
4204 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4205 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4206 Con_Printf("GL_VERSION: %s\n", gl_version);
4207 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4208 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4210 VID_CheckExtensions();
4212 // LordHavoc: report supported extensions
4213 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4215 // clear to black (loading plaque will be seen over this)
4216 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4219 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4223 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4225 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4228 p = r_refdef.view.frustum + i;
4233 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4237 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4241 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4245 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4249 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4253 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4257 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4261 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4269 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4273 for (i = 0;i < numplanes;i++)
4280 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4284 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4288 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4292 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4296 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4300 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4304 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4308 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4316 //==================================================================================
4318 // LordHavoc: this stores temporary data used within the same frame
4320 typedef struct r_framedata_mem_s
4322 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4323 size_t size; // how much usable space
4324 size_t current; // how much space in use
4325 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4326 size_t wantedsize; // how much space was allocated
4327 unsigned char *data; // start of real data (16byte aligned)
4331 static r_framedata_mem_t *r_framedata_mem;
4333 void R_FrameData_Reset(void)
4335 while (r_framedata_mem)
4337 r_framedata_mem_t *next = r_framedata_mem->purge;
4338 Mem_Free(r_framedata_mem);
4339 r_framedata_mem = next;
4343 void R_FrameData_Resize(void)
4346 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4347 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4348 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4350 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4351 newmem->wantedsize = wantedsize;
4352 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4353 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4354 newmem->current = 0;
4356 newmem->purge = r_framedata_mem;
4357 r_framedata_mem = newmem;
4361 void R_FrameData_NewFrame(void)
4363 R_FrameData_Resize();
4364 if (!r_framedata_mem)
4366 // if we ran out of space on the last frame, free the old memory now
4367 while (r_framedata_mem->purge)
4369 // repeatedly remove the second item in the list, leaving only head
4370 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4371 Mem_Free(r_framedata_mem->purge);
4372 r_framedata_mem->purge = next;
4374 // reset the current mem pointer
4375 r_framedata_mem->current = 0;
4376 r_framedata_mem->mark = 0;
4379 void *R_FrameData_Alloc(size_t size)
4383 // align to 16 byte boundary - the data pointer is already aligned, so we
4384 // only need to ensure the size of every allocation is also aligned
4385 size = (size + 15) & ~15;
4387 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4389 // emergency - we ran out of space, allocate more memory
4390 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4391 R_FrameData_Resize();
4394 data = r_framedata_mem->data + r_framedata_mem->current;
4395 r_framedata_mem->current += size;
4397 // count the usage for stats
4398 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4399 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4401 return (void *)data;
4404 void *R_FrameData_Store(size_t size, void *data)
4406 void *d = R_FrameData_Alloc(size);
4408 memcpy(d, data, size);
4412 void R_FrameData_SetMark(void)
4414 if (!r_framedata_mem)
4416 r_framedata_mem->mark = r_framedata_mem->current;
4419 void R_FrameData_ReturnToMark(void)
4421 if (!r_framedata_mem)
4423 r_framedata_mem->current = r_framedata_mem->mark;
4426 //==================================================================================
4428 // LordHavoc: animcache originally written by Echon, rewritten since then
4431 * Animation cache prevents re-generating mesh data for an animated model
4432 * multiple times in one frame for lighting, shadowing, reflections, etc.
4435 void R_AnimCache_Free(void)
4439 void R_AnimCache_ClearCache(void)
4442 entity_render_t *ent;
4444 for (i = 0;i < r_refdef.scene.numentities;i++)
4446 ent = r_refdef.scene.entities[i];
4447 ent->animcache_vertex3f = NULL;
4448 ent->animcache_normal3f = NULL;
4449 ent->animcache_svector3f = NULL;
4450 ent->animcache_tvector3f = NULL;
4451 ent->animcache_vertexmesh = NULL;
4452 ent->animcache_vertex3fbuffer = NULL;
4453 ent->animcache_vertexmeshbuffer = NULL;
4457 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4461 // check if we need the meshbuffers
4462 if (!vid.useinterleavedarrays)
4465 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4466 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4467 // TODO: upload vertex3f buffer?
4468 if (ent->animcache_vertexmesh)
4470 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4471 for (i = 0;i < numvertices;i++)
4472 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4473 if (ent->animcache_svector3f)
4474 for (i = 0;i < numvertices;i++)
4475 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4476 if (ent->animcache_tvector3f)
4477 for (i = 0;i < numvertices;i++)
4478 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4479 if (ent->animcache_normal3f)
4480 for (i = 0;i < numvertices;i++)
4481 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4482 // TODO: upload vertexmeshbuffer?
4486 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4488 dp_model_t *model = ent->model;
4490 // see if it's already cached this frame
4491 if (ent->animcache_vertex3f)
4493 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4494 if (wantnormals || wanttangents)
4496 if (ent->animcache_normal3f)
4497 wantnormals = false;
4498 if (ent->animcache_svector3f)
4499 wanttangents = false;
4500 if (wantnormals || wanttangents)
4502 numvertices = model->surfmesh.num_vertices;
4504 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4507 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4508 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4510 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4511 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4517 // see if this ent is worth caching
4518 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4520 // get some memory for this entity and generate mesh data
4521 numvertices = model->surfmesh.num_vertices;
4522 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4524 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4527 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4528 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4530 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4531 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4536 void R_AnimCache_CacheVisibleEntities(void)
4539 qboolean wantnormals = true;
4540 qboolean wanttangents = !r_showsurfaces.integer;
4542 switch(vid.renderpath)
4544 case RENDERPATH_GL20:
4545 case RENDERPATH_D3D9:
4546 case RENDERPATH_D3D10:
4547 case RENDERPATH_D3D11:
4548 case RENDERPATH_GLES2:
4550 case RENDERPATH_GL13:
4551 case RENDERPATH_GL11:
4552 wanttangents = false;
4554 case RENDERPATH_SOFT:
4558 if (r_shownormals.integer)
4559 wanttangents = wantnormals = true;
4561 // TODO: thread this
4562 // NOTE: R_PrepareRTLights() also caches entities
4564 for (i = 0;i < r_refdef.scene.numentities;i++)
4565 if (r_refdef.viewcache.entityvisible[i])
4566 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4569 //==================================================================================
4571 static void R_View_UpdateEntityLighting (void)
4574 entity_render_t *ent;
4575 vec3_t tempdiffusenormal, avg;
4576 vec_t f, fa, fd, fdd;
4577 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4579 for (i = 0;i < r_refdef.scene.numentities;i++)
4581 ent = r_refdef.scene.entities[i];
4583 // skip unseen models
4584 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4588 if (ent->model && ent->model->brush.num_leafs)
4590 // TODO: use modellight for r_ambient settings on world?
4591 VectorSet(ent->modellight_ambient, 0, 0, 0);
4592 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4593 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4597 // fetch the lighting from the worldmodel data
4598 VectorClear(ent->modellight_ambient);
4599 VectorClear(ent->modellight_diffuse);
4600 VectorClear(tempdiffusenormal);
4601 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4604 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4606 // complete lightning for lit sprites
4607 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4608 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4610 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4611 org[2] = org[2] + r_overheadsprites_pushback.value;
4612 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4615 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4617 if(ent->flags & RENDER_EQUALIZE)
4619 // first fix up ambient lighting...
4620 if(r_equalize_entities_minambient.value > 0)
4622 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4625 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4626 if(fa < r_equalize_entities_minambient.value * fd)
4629 // fa'/fd' = minambient
4630 // fa'+0.25*fd' = fa+0.25*fd
4632 // fa' = fd' * minambient
4633 // fd'*(0.25+minambient) = fa+0.25*fd
4635 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4636 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4638 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4639 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
4640 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4641 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4646 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4648 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4649 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4653 // adjust brightness and saturation to target
4654 avg[0] = avg[1] = avg[2] = fa / f;
4655 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4656 avg[0] = avg[1] = avg[2] = fd / f;
4657 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4663 VectorSet(ent->modellight_ambient, 1, 1, 1);
4665 // move the light direction into modelspace coordinates for lighting code
4666 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4667 if(VectorLength2(ent->modellight_lightdir) == 0)
4668 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4669 VectorNormalize(ent->modellight_lightdir);
4673 #define MAX_LINEOFSIGHTTRACES 64
4675 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4678 vec3_t boxmins, boxmaxs;
4681 dp_model_t *model = r_refdef.scene.worldmodel;
4683 if (!model || !model->brush.TraceLineOfSight)
4686 // expand the box a little
4687 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4688 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4689 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4690 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4691 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4692 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4694 // return true if eye is inside enlarged box
4695 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4699 VectorCopy(eye, start);
4700 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4701 if (model->brush.TraceLineOfSight(model, start, end))
4704 // try various random positions
4705 for (i = 0;i < numsamples;i++)
4707 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4708 if (model->brush.TraceLineOfSight(model, start, end))
4716 static void R_View_UpdateEntityVisible (void)
4721 entity_render_t *ent;
4723 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4724 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4725 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
4726 : RENDER_EXTERIORMODEL;
4727 if (!r_drawviewmodel.integer)
4728 renderimask |= RENDER_VIEWMODEL;
4729 if (!r_drawexteriormodel.integer)
4730 renderimask |= RENDER_EXTERIORMODEL;
4731 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4733 // worldmodel can check visibility
4734 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4735 for (i = 0;i < r_refdef.scene.numentities;i++)
4737 ent = r_refdef.scene.entities[i];
4738 if (!(ent->flags & renderimask))
4739 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)))
4740 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))
4741 r_refdef.viewcache.entityvisible[i] = true;
4743 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4744 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4746 for (i = 0;i < r_refdef.scene.numentities;i++)
4748 ent = r_refdef.scene.entities[i];
4749 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4751 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4753 continue; // temp entities do pvs only
4754 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4755 ent->last_trace_visibility = realtime;
4756 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4757 r_refdef.viewcache.entityvisible[i] = 0;
4764 // no worldmodel or it can't check visibility
4765 for (i = 0;i < r_refdef.scene.numentities;i++)
4767 ent = r_refdef.scene.entities[i];
4768 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));
4773 /// only used if skyrendermasked, and normally returns false
4774 int R_DrawBrushModelsSky (void)
4777 entity_render_t *ent;
4780 for (i = 0;i < r_refdef.scene.numentities;i++)
4782 if (!r_refdef.viewcache.entityvisible[i])
4784 ent = r_refdef.scene.entities[i];
4785 if (!ent->model || !ent->model->DrawSky)
4787 ent->model->DrawSky(ent);
4793 static void R_DrawNoModel(entity_render_t *ent);
4794 static void R_DrawModels(void)
4797 entity_render_t *ent;
4799 for (i = 0;i < r_refdef.scene.numentities;i++)
4801 if (!r_refdef.viewcache.entityvisible[i])
4803 ent = r_refdef.scene.entities[i];
4804 r_refdef.stats.entities++;
4805 if (ent->model && ent->model->Draw != NULL)
4806 ent->model->Draw(ent);
4812 static void R_DrawModelsDepth(void)
4815 entity_render_t *ent;
4817 for (i = 0;i < r_refdef.scene.numentities;i++)
4819 if (!r_refdef.viewcache.entityvisible[i])
4821 ent = r_refdef.scene.entities[i];
4822 if (ent->model && ent->model->DrawDepth != NULL)
4823 ent->model->DrawDepth(ent);
4827 static void R_DrawModelsDebug(void)
4830 entity_render_t *ent;
4832 for (i = 0;i < r_refdef.scene.numentities;i++)
4834 if (!r_refdef.viewcache.entityvisible[i])
4836 ent = r_refdef.scene.entities[i];
4837 if (ent->model && ent->model->DrawDebug != NULL)
4838 ent->model->DrawDebug(ent);
4842 static void R_DrawModelsAddWaterPlanes(void)
4845 entity_render_t *ent;
4847 for (i = 0;i < r_refdef.scene.numentities;i++)
4849 if (!r_refdef.viewcache.entityvisible[i])
4851 ent = r_refdef.scene.entities[i];
4852 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4853 ent->model->DrawAddWaterPlanes(ent);
4857 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4859 if (r_hdr_irisadaptation.integer)
4863 vec3_t diffusenormal;
4868 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4869 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4870 brightness = max(0.0000001f, brightness);
4871 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4872 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4873 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4874 current = r_hdr_irisadaptation_value.value;
4876 current = min(current + adjust, goal);
4877 else if (current > goal)
4878 current = max(current - adjust, goal);
4879 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4880 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4882 else if (r_hdr_irisadaptation_value.value != 1.0f)
4883 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4886 static void R_View_SetFrustum(const int *scissor)
4889 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4890 vec3_t forward, left, up, origin, v;
4894 // flipped x coordinates (because x points left here)
4895 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4896 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4898 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4899 switch(vid.renderpath)
4901 case RENDERPATH_D3D9:
4902 case RENDERPATH_D3D10:
4903 case RENDERPATH_D3D11:
4904 // non-flipped y coordinates
4905 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4906 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4908 case RENDERPATH_SOFT:
4909 case RENDERPATH_GL11:
4910 case RENDERPATH_GL13:
4911 case RENDERPATH_GL20:
4912 case RENDERPATH_GLES2:
4913 // non-flipped y coordinates
4914 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4915 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4920 // we can't trust r_refdef.view.forward and friends in reflected scenes
4921 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4924 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4925 r_refdef.view.frustum[0].normal[1] = 0 - 0;
4926 r_refdef.view.frustum[0].normal[2] = -1 - 0;
4927 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4928 r_refdef.view.frustum[1].normal[1] = 0 + 0;
4929 r_refdef.view.frustum[1].normal[2] = -1 + 0;
4930 r_refdef.view.frustum[2].normal[0] = 0 - 0;
4931 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4932 r_refdef.view.frustum[2].normal[2] = -1 - 0;
4933 r_refdef.view.frustum[3].normal[0] = 0 + 0;
4934 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4935 r_refdef.view.frustum[3].normal[2] = -1 + 0;
4939 zNear = r_refdef.nearclip;
4940 nudge = 1.0 - 1.0 / (1<<23);
4941 r_refdef.view.frustum[4].normal[0] = 0 - 0;
4942 r_refdef.view.frustum[4].normal[1] = 0 - 0;
4943 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4944 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4945 r_refdef.view.frustum[5].normal[0] = 0 + 0;
4946 r_refdef.view.frustum[5].normal[1] = 0 + 0;
4947 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4948 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4954 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4955 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4956 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4957 r_refdef.view.frustum[0].dist = m[15] - m[12];
4959 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4960 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4961 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4962 r_refdef.view.frustum[1].dist = m[15] + m[12];
4964 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4965 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4966 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4967 r_refdef.view.frustum[2].dist = m[15] - m[13];
4969 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4970 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4971 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4972 r_refdef.view.frustum[3].dist = m[15] + m[13];
4974 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4975 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4976 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4977 r_refdef.view.frustum[4].dist = m[15] - m[14];
4979 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
4980 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
4981 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
4982 r_refdef.view.frustum[5].dist = m[15] + m[14];
4985 if (r_refdef.view.useperspective)
4987 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
4988 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]);
4989 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]);
4990 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]);
4991 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]);
4993 // then the normals from the corners relative to origin
4994 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
4995 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
4996 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
4997 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
4999 // in a NORMAL view, forward cross left == up
5000 // in a REFLECTED view, forward cross left == down
5001 // so our cross products above need to be adjusted for a left handed coordinate system
5002 CrossProduct(forward, left, v);
5003 if(DotProduct(v, up) < 0)
5005 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5006 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5007 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5008 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5011 // Leaving those out was a mistake, those were in the old code, and they
5012 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5013 // I couldn't reproduce it after adding those normalizations. --blub
5014 VectorNormalize(r_refdef.view.frustum[0].normal);
5015 VectorNormalize(r_refdef.view.frustum[1].normal);
5016 VectorNormalize(r_refdef.view.frustum[2].normal);
5017 VectorNormalize(r_refdef.view.frustum[3].normal);
5019 // make the corners absolute
5020 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5021 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5022 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5023 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5026 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5028 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5029 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5030 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5031 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5032 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5036 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5037 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5038 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5039 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5040 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5041 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5042 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5043 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5044 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5045 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5047 r_refdef.view.numfrustumplanes = 5;
5049 if (r_refdef.view.useclipplane)
5051 r_refdef.view.numfrustumplanes = 6;
5052 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5055 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5056 PlaneClassify(r_refdef.view.frustum + i);
5058 // LordHavoc: note to all quake engine coders, Quake had a special case
5059 // for 90 degrees which assumed a square view (wrong), so I removed it,
5060 // Quake2 has it disabled as well.
5062 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5063 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5064 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5065 //PlaneClassify(&frustum[0]);
5067 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5068 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5069 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5070 //PlaneClassify(&frustum[1]);
5072 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5073 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5074 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5075 //PlaneClassify(&frustum[2]);
5077 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5078 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5079 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5080 //PlaneClassify(&frustum[3]);
5083 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5084 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5085 //PlaneClassify(&frustum[4]);
5088 void R_View_UpdateWithScissor(const int *myscissor)
5090 R_Main_ResizeViewCache();
5091 R_View_SetFrustum(myscissor);
5092 R_View_WorldVisibility(r_refdef.view.useclipplane);
5093 R_View_UpdateEntityVisible();
5094 R_View_UpdateEntityLighting();
5097 void R_View_Update(void)
5099 R_Main_ResizeViewCache();
5100 R_View_SetFrustum(NULL);
5101 R_View_WorldVisibility(r_refdef.view.useclipplane);
5102 R_View_UpdateEntityVisible();
5103 R_View_UpdateEntityLighting();
5106 float viewscalefpsadjusted = 1.0f;
5108 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5110 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5111 scale = bound(0.03125f, scale, 1.0f);
5112 *outwidth = (int)ceil(width * scale);
5113 *outheight = (int)ceil(height * scale);
5116 void R_Mesh_SetMainRenderTargets(void)
5118 if (r_bloomstate.fbo_framebuffer)
5119 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5121 R_Mesh_ResetRenderTargets();
5124 void R_SetupView(qboolean allowwaterclippingplane)
5126 const float *customclipplane = NULL;
5128 int scaledwidth, scaledheight;
5129 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5131 // LordHavoc: couldn't figure out how to make this approach the
5132 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5133 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5134 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5135 dist = r_refdef.view.clipplane.dist;
5136 plane[0] = r_refdef.view.clipplane.normal[0];
5137 plane[1] = r_refdef.view.clipplane.normal[1];
5138 plane[2] = r_refdef.view.clipplane.normal[2];
5140 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5143 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5144 if (!r_refdef.view.useperspective)
5145 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);
5146 else if (vid.stencil && r_useinfinitefarclip.integer)
5147 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);
5149 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);
5150 R_Mesh_SetMainRenderTargets();
5151 R_SetViewport(&r_refdef.view.viewport);
5152 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5154 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5155 float screenplane[4];
5156 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5157 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5158 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5159 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5160 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5164 void R_EntityMatrix(const matrix4x4_t *matrix)
5166 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5168 gl_modelmatrixchanged = false;
5169 gl_modelmatrix = *matrix;
5170 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5171 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5172 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5173 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5175 switch(vid.renderpath)
5177 case RENDERPATH_D3D9:
5179 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5180 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5183 case RENDERPATH_D3D10:
5184 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5186 case RENDERPATH_D3D11:
5187 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5189 case RENDERPATH_GL13:
5190 case RENDERPATH_GL11:
5191 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5193 case RENDERPATH_SOFT:
5194 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5195 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5197 case RENDERPATH_GL20:
5198 case RENDERPATH_GLES2:
5199 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5200 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5206 void R_ResetViewRendering2D(void)
5208 r_viewport_t viewport;
5211 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5212 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);
5213 R_Mesh_ResetRenderTargets();
5214 R_SetViewport(&viewport);
5215 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5216 GL_Color(1, 1, 1, 1);
5217 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5218 GL_BlendFunc(GL_ONE, GL_ZERO);
5219 GL_ScissorTest(false);
5220 GL_DepthMask(false);
5221 GL_DepthRange(0, 1);
5222 GL_DepthTest(false);
5223 GL_DepthFunc(GL_LEQUAL);
5224 R_EntityMatrix(&identitymatrix);
5225 R_Mesh_ResetTextureState();
5226 GL_PolygonOffset(0, 0);
5227 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5228 switch(vid.renderpath)
5230 case RENDERPATH_GL11:
5231 case RENDERPATH_GL13:
5232 case RENDERPATH_GL20:
5233 case RENDERPATH_GLES2:
5234 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5236 case RENDERPATH_D3D9:
5237 case RENDERPATH_D3D10:
5238 case RENDERPATH_D3D11:
5239 case RENDERPATH_SOFT:
5242 GL_CullFace(GL_NONE);
5245 void R_ResetViewRendering3D(void)
5250 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5251 GL_Color(1, 1, 1, 1);
5252 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5253 GL_BlendFunc(GL_ONE, GL_ZERO);
5254 GL_ScissorTest(true);
5256 GL_DepthRange(0, 1);
5258 GL_DepthFunc(GL_LEQUAL);
5259 R_EntityMatrix(&identitymatrix);
5260 R_Mesh_ResetTextureState();
5261 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5262 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5263 switch(vid.renderpath)
5265 case RENDERPATH_GL11:
5266 case RENDERPATH_GL13:
5267 case RENDERPATH_GL20:
5268 case RENDERPATH_GLES2:
5269 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5271 case RENDERPATH_D3D9:
5272 case RENDERPATH_D3D10:
5273 case RENDERPATH_D3D11:
5274 case RENDERPATH_SOFT:
5277 GL_CullFace(r_refdef.view.cullface_back);
5282 R_RenderView_UpdateViewVectors
5285 static void R_RenderView_UpdateViewVectors(void)
5287 // break apart the view matrix into vectors for various purposes
5288 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5289 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5290 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5291 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5292 // make an inverted copy of the view matrix for tracking sprites
5293 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5296 void R_RenderScene(void);
5297 void R_RenderWaterPlanes(void);
5299 static void R_Water_StartFrame(void)
5302 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5303 r_waterstate_waterplane_t *p;
5305 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5308 switch(vid.renderpath)
5310 case RENDERPATH_GL20:
5311 case RENDERPATH_D3D9:
5312 case RENDERPATH_D3D10:
5313 case RENDERPATH_D3D11:
5314 case RENDERPATH_SOFT:
5315 case RENDERPATH_GLES2:
5317 case RENDERPATH_GL13:
5318 case RENDERPATH_GL11:
5322 // set waterwidth and waterheight to the water resolution that will be
5323 // used (often less than the screen resolution for faster rendering)
5324 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5325 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5327 // calculate desired texture sizes
5328 // can't use water if the card does not support the texture size
5329 if (!r_water.integer || r_showsurfaces.integer)
5330 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5331 else if (vid.support.arb_texture_non_power_of_two)
5333 texturewidth = waterwidth;
5334 textureheight = waterheight;
5335 camerawidth = waterwidth;
5336 cameraheight = waterheight;
5340 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5341 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5342 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5343 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5346 // allocate textures as needed
5347 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5349 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5350 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5352 if (p->texture_refraction)
5353 R_FreeTexture(p->texture_refraction);
5354 p->texture_refraction = NULL;
5355 if (p->texture_reflection)
5356 R_FreeTexture(p->texture_reflection);
5357 p->texture_reflection = NULL;
5358 if (p->texture_camera)
5359 R_FreeTexture(p->texture_camera);
5360 p->texture_camera = NULL;
5362 memset(&r_waterstate, 0, sizeof(r_waterstate));
5363 r_waterstate.texturewidth = texturewidth;
5364 r_waterstate.textureheight = textureheight;
5365 r_waterstate.camerawidth = camerawidth;
5366 r_waterstate.cameraheight = cameraheight;
5369 if (r_waterstate.texturewidth)
5371 r_waterstate.enabled = true;
5373 // when doing a reduced render (HDR) we want to use a smaller area
5374 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5375 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5377 // set up variables that will be used in shader setup
5378 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5379 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5380 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5381 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5384 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5385 r_waterstate.numwaterplanes = 0;
5388 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5390 int triangleindex, planeindex;
5396 r_waterstate_waterplane_t *p;
5397 texture_t *t = R_GetCurrentTexture(surface->texture);
5399 // just use the first triangle with a valid normal for any decisions
5400 VectorClear(normal);
5401 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5403 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5404 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5405 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5406 TriangleNormal(vert[0], vert[1], vert[2], normal);
5407 if (VectorLength2(normal) >= 0.001)
5411 VectorCopy(normal, plane.normal);
5412 VectorNormalize(plane.normal);
5413 plane.dist = DotProduct(vert[0], plane.normal);
5414 PlaneClassify(&plane);
5415 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5417 // skip backfaces (except if nocullface is set)
5418 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5420 VectorNegate(plane.normal, plane.normal);
5422 PlaneClassify(&plane);
5426 // find a matching plane if there is one
5427 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5428 if(p->camera_entity == t->camera_entity)
5429 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5431 if (planeindex >= r_waterstate.maxwaterplanes)
5432 return; // nothing we can do, out of planes
5434 // if this triangle does not fit any known plane rendered this frame, add one
5435 if (planeindex >= r_waterstate.numwaterplanes)
5437 // store the new plane
5438 r_waterstate.numwaterplanes++;
5440 // clear materialflags and pvs
5441 p->materialflags = 0;
5442 p->pvsvalid = false;
5443 p->camera_entity = t->camera_entity;
5444 VectorCopy(surface->mins, p->mins);
5445 VectorCopy(surface->maxs, p->maxs);
5450 p->mins[0] = min(p->mins[0], surface->mins[0]);
5451 p->mins[1] = min(p->mins[1], surface->mins[1]);
5452 p->mins[2] = min(p->mins[2], surface->mins[2]);
5453 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5454 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5455 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5457 // merge this surface's materialflags into the waterplane
5458 p->materialflags |= t->currentmaterialflags;
5459 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5461 // merge this surface's PVS into the waterplane
5462 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5463 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5464 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5466 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5472 static void R_Water_ProcessPlanes(void)
5475 r_refdef_view_t originalview;
5476 r_refdef_view_t myview;
5478 r_waterstate_waterplane_t *p;
5481 originalview = r_refdef.view;
5483 // make sure enough textures are allocated
5484 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5486 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5488 if (!p->texture_refraction)
5489 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);
5490 if (!p->texture_refraction)
5493 else if (p->materialflags & MATERIALFLAG_CAMERA)
5495 if (!p->texture_camera)
5496 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);
5497 if (!p->texture_camera)
5501 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5503 if (!p->texture_reflection)
5504 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);
5505 if (!p->texture_reflection)
5511 r_refdef.view = originalview;
5512 r_refdef.view.showdebug = false;
5513 r_refdef.view.width = r_waterstate.waterwidth;
5514 r_refdef.view.height = r_waterstate.waterheight;
5515 r_refdef.view.useclipplane = true;
5516 myview = r_refdef.view;
5517 r_waterstate.renderingscene = true;
5518 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5520 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5522 r_refdef.view = myview;
5523 if(r_water_scissormode.integer)
5526 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5527 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5530 // render reflected scene and copy into texture
5531 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5532 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5533 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5534 r_refdef.view.clipplane = p->plane;
5536 // reverse the cullface settings for this render
5537 r_refdef.view.cullface_front = GL_FRONT;
5538 r_refdef.view.cullface_back = GL_BACK;
5539 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5541 r_refdef.view.usecustompvs = true;
5543 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5545 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5548 R_ResetViewRendering3D();
5549 R_ClearScreen(r_refdef.fogenabled);
5550 if(r_water_scissormode.integer & 2)
5551 R_View_UpdateWithScissor(myscissor);
5554 if(r_water_scissormode.integer & 1)
5555 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5558 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);
5561 // render the normal view scene and copy into texture
5562 // (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)
5563 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5565 r_refdef.view = myview;
5566 if(r_water_scissormode.integer)
5569 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5570 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5573 r_waterstate.renderingrefraction = true;
5575 r_refdef.view.clipplane = p->plane;
5576 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5577 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5579 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5581 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5582 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5583 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5584 R_RenderView_UpdateViewVectors();
5585 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5587 r_refdef.view.usecustompvs = true;
5588 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);
5592 PlaneClassify(&r_refdef.view.clipplane);
5594 R_ResetViewRendering3D();
5595 R_ClearScreen(r_refdef.fogenabled);
5596 if(r_water_scissormode.integer & 2)
5597 R_View_UpdateWithScissor(myscissor);
5600 if(r_water_scissormode.integer & 1)
5601 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5604 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);
5605 r_waterstate.renderingrefraction = false;
5607 else if (p->materialflags & MATERIALFLAG_CAMERA)
5609 r_refdef.view = myview;
5611 r_refdef.view.clipplane = p->plane;
5612 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5613 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5615 r_refdef.view.width = r_waterstate.camerawidth;
5616 r_refdef.view.height = r_waterstate.cameraheight;
5617 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5618 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5620 if(p->camera_entity)
5622 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5623 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5626 // note: all of the view is used for displaying... so
5627 // there is no use in scissoring
5629 // reverse the cullface settings for this render
5630 r_refdef.view.cullface_front = GL_FRONT;
5631 r_refdef.view.cullface_back = GL_BACK;
5632 // also reverse the view matrix
5633 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
5634 R_RenderView_UpdateViewVectors();
5635 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5637 r_refdef.view.usecustompvs = true;
5638 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);
5641 // camera needs no clipplane
5642 r_refdef.view.useclipplane = false;
5644 PlaneClassify(&r_refdef.view.clipplane);
5646 R_ResetViewRendering3D();
5647 R_ClearScreen(r_refdef.fogenabled);
5651 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);
5652 r_waterstate.renderingrefraction = false;
5656 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5657 r_waterstate.renderingscene = false;
5658 r_refdef.view = originalview;
5659 R_ResetViewRendering3D();
5660 R_ClearScreen(r_refdef.fogenabled);
5664 r_refdef.view = originalview;
5665 r_waterstate.renderingscene = false;
5666 Cvar_SetValueQuick(&r_water, 0);
5667 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5671 void R_Bloom_StartFrame(void)
5673 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5674 int viewwidth, viewheight;
5677 if (r_viewscale_fpsscaling.integer)
5679 double actualframetime;
5680 double targetframetime;
5682 actualframetime = r_refdef.lastdrawscreentime;
5683 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5684 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5685 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5686 if (r_viewscale_fpsscaling_stepsize.value > 0)
5687 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5688 viewscalefpsadjusted += adjust;
5689 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5692 viewscalefpsadjusted = 1.0f;
5694 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5696 switch(vid.renderpath)
5698 case RENDERPATH_GL20:
5699 case RENDERPATH_D3D9:
5700 case RENDERPATH_D3D10:
5701 case RENDERPATH_D3D11:
5702 case RENDERPATH_SOFT:
5703 case RENDERPATH_GLES2:
5705 case RENDERPATH_GL13:
5706 case RENDERPATH_GL11:
5710 // set bloomwidth and bloomheight to the bloom resolution that will be
5711 // used (often less than the screen resolution for faster rendering)
5712 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5713 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5714 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5715 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5716 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5718 // calculate desired texture sizes
5719 if (vid.support.arb_texture_non_power_of_two)
5721 screentexturewidth = vid.width;
5722 screentextureheight = vid.height;
5723 bloomtexturewidth = r_bloomstate.bloomwidth;
5724 bloomtextureheight = r_bloomstate.bloomheight;
5728 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
5729 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
5730 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
5731 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
5734 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))
5736 Cvar_SetValueQuick(&r_hdr, 0);
5737 Cvar_SetValueQuick(&r_bloom, 0);
5738 Cvar_SetValueQuick(&r_motionblur, 0);
5739 Cvar_SetValueQuick(&r_damageblur, 0);
5742 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)
5743 screentexturewidth = screentextureheight = 0;
5744 if (!r_hdr.integer && !r_bloom.integer)
5745 bloomtexturewidth = bloomtextureheight = 0;
5747 textype = TEXTYPE_COLORBUFFER;
5748 switch (vid.renderpath)
5750 case RENDERPATH_GL20:
5751 case RENDERPATH_GLES2:
5752 if (vid.support.ext_framebuffer_object)
5754 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5755 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5758 case RENDERPATH_D3D9:
5759 case RENDERPATH_D3D10:
5760 case RENDERPATH_D3D11:
5761 case RENDERPATH_SOFT:
5762 case RENDERPATH_GL13:
5763 case RENDERPATH_GL11:
5767 // allocate textures as needed
5768 if (r_bloomstate.screentexturewidth != screentexturewidth
5769 || r_bloomstate.screentextureheight != screentextureheight
5770 || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5771 || r_bloomstate.bloomtextureheight != bloomtextureheight
5772 || r_bloomstate.texturetype != textype
5773 || r_bloomstate.viewfbo != r_viewfbo.integer)
5775 if (r_bloomstate.texture_bloom)
5776 R_FreeTexture(r_bloomstate.texture_bloom);
5777 r_bloomstate.texture_bloom = NULL;
5778 if (r_bloomstate.texture_screen)
5779 R_FreeTexture(r_bloomstate.texture_screen);
5780 r_bloomstate.texture_screen = NULL;
5781 if (r_bloomstate.fbo_framebuffer)
5782 R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5783 r_bloomstate.fbo_framebuffer = 0;
5784 if (r_bloomstate.texture_framebuffercolor)
5785 R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5786 r_bloomstate.texture_framebuffercolor = NULL;
5787 if (r_bloomstate.texture_framebufferdepth)
5788 R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5789 r_bloomstate.texture_framebufferdepth = NULL;
5790 r_bloomstate.screentexturewidth = screentexturewidth;
5791 r_bloomstate.screentextureheight = screentextureheight;
5792 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5793 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);
5794 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5796 // FIXME: choose depth bits based on a cvar
5797 r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5798 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);
5799 r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5800 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5801 // render depth into one texture and normalmap into the other
5805 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5806 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5807 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
5808 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
5809 Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
5812 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5813 r_bloomstate.bloomtextureheight = bloomtextureheight;
5814 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5815 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);
5816 r_bloomstate.viewfbo = r_viewfbo.integer;
5817 r_bloomstate.texturetype = textype;
5820 // when doing a reduced render (HDR) we want to use a smaller area
5821 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5822 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5823 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5824 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5825 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5827 // set up a texcoord array for the full resolution screen image
5828 // (we have to keep this around to copy back during final render)
5829 r_bloomstate.screentexcoord2f[0] = 0;
5830 r_bloomstate.screentexcoord2f[1] = (float)viewheight / (float)r_bloomstate.screentextureheight;
5831 r_bloomstate.screentexcoord2f[2] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
5832 r_bloomstate.screentexcoord2f[3] = (float)viewheight / (float)r_bloomstate.screentextureheight;
5833 r_bloomstate.screentexcoord2f[4] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
5834 r_bloomstate.screentexcoord2f[5] = 0;
5835 r_bloomstate.screentexcoord2f[6] = 0;
5836 r_bloomstate.screentexcoord2f[7] = 0;
5838 // set up a texcoord array for the reduced resolution bloom image
5839 // (which will be additive blended over the screen image)
5840 r_bloomstate.bloomtexcoord2f[0] = 0;
5841 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5842 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5843 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5844 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5845 r_bloomstate.bloomtexcoord2f[5] = 0;
5846 r_bloomstate.bloomtexcoord2f[6] = 0;
5847 r_bloomstate.bloomtexcoord2f[7] = 0;
5849 switch(vid.renderpath)
5851 case RENDERPATH_GL11:
5852 case RENDERPATH_GL13:
5853 case RENDERPATH_GL20:
5854 case RENDERPATH_SOFT:
5855 case RENDERPATH_GLES2:
5857 case RENDERPATH_D3D9:
5858 case RENDERPATH_D3D10:
5859 case RENDERPATH_D3D11:
5862 for (i = 0;i < 4;i++)
5864 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5865 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5866 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5867 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5873 if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
5875 r_bloomstate.enabled = true;
5876 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
5879 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);
5881 if (r_bloomstate.fbo_framebuffer)
5882 r_refdef.view.clear = true;
5885 void R_Bloom_CopyBloomTexture(float colorscale)
5887 r_refdef.stats.bloom++;
5889 // scale down screen texture to the bloom texture size
5891 R_Mesh_SetMainRenderTargets();
5892 R_SetViewport(&r_bloomstate.viewport);
5893 GL_BlendFunc(GL_ONE, GL_ZERO);
5894 GL_Color(colorscale, colorscale, colorscale, 1);
5895 // 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...
5896 switch(vid.renderpath)
5898 case RENDERPATH_GL11:
5899 case RENDERPATH_GL13:
5900 case RENDERPATH_GL20:
5901 case RENDERPATH_SOFT:
5902 case RENDERPATH_GLES2:
5903 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5905 case RENDERPATH_D3D9:
5906 case RENDERPATH_D3D10:
5907 case RENDERPATH_D3D11:
5908 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5911 // TODO: do boxfilter scale-down in shader?
5912 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5913 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5914 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5916 // we now have a bloom image in the framebuffer
5917 // copy it into the bloom image texture for later processing
5918 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);
5919 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5922 void R_Bloom_CopyHDRTexture(void)
5924 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);
5925 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5928 void R_Bloom_MakeTexture(void)
5931 float xoffset, yoffset, r, brighten;
5933 r_refdef.stats.bloom++;
5935 R_ResetViewRendering2D();
5937 // we have a bloom image in the framebuffer
5939 R_SetViewport(&r_bloomstate.viewport);
5941 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5944 r = bound(0, r_bloom_colorexponent.value / x, 1);
5945 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5947 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5948 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5949 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5950 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5952 // copy the vertically blurred bloom view to a texture
5953 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);
5954 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5957 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5958 brighten = r_bloom_brighten.value;
5959 if (r_bloomstate.hdr)
5960 brighten *= r_hdr_range.value;
5961 brighten = sqrt(brighten);
5963 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5964 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5966 for (dir = 0;dir < 2;dir++)
5968 // blend on at multiple vertical offsets to achieve a vertical blur
5969 // TODO: do offset blends using GLSL
5970 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5971 GL_BlendFunc(GL_ONE, GL_ZERO);
5972 for (x = -range;x <= range;x++)
5974 if (!dir){xoffset = 0;yoffset = x;}
5975 else {xoffset = x;yoffset = 0;}
5976 xoffset /= (float)r_bloomstate.bloomtexturewidth;
5977 yoffset /= (float)r_bloomstate.bloomtextureheight;
5978 // compute a texcoord array with the specified x and y offset
5979 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
5980 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5981 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5982 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5983 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5984 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
5985 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
5986 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
5987 // this r value looks like a 'dot' particle, fading sharply to
5988 // black at the edges
5989 // (probably not realistic but looks good enough)
5990 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
5991 //r = brighten/(range*2+1);
5992 r = brighten / (range * 2 + 1);
5994 r *= (1 - x*x/(float)(range*range));
5995 GL_Color(r, r, r, 1);
5996 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
5997 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5998 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5999 GL_BlendFunc(GL_ONE, GL_ONE);
6002 // copy the vertically blurred bloom view to a texture
6003 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);
6004 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6008 void R_HDR_RenderBloomTexture(void)
6010 int oldwidth, oldheight;
6011 float oldcolorscale;
6012 qboolean oldwaterstate;
6014 oldwaterstate = r_waterstate.enabled;
6015 oldcolorscale = r_refdef.view.colorscale;
6016 oldwidth = r_refdef.view.width;
6017 oldheight = r_refdef.view.height;
6018 r_refdef.view.width = r_bloomstate.bloomwidth;
6019 r_refdef.view.height = r_bloomstate.bloomheight;
6021 if(r_hdr.integer < 2)
6022 r_waterstate.enabled = false;
6024 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
6025 // TODO: add exposure compensation features
6026 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6028 r_refdef.view.showdebug = false;
6029 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6031 R_ResetViewRendering3D();
6033 R_ClearScreen(r_refdef.fogenabled);
6034 if (r_timereport_active)
6035 R_TimeReport("HDRclear");
6038 if (r_timereport_active)
6039 R_TimeReport("visibility");
6041 // only do secondary renders with HDR if r_hdr is 2 or higher
6042 r_waterstate.numwaterplanes = 0;
6043 if (r_waterstate.enabled)
6044 R_RenderWaterPlanes();
6046 r_refdef.view.showdebug = true;
6048 r_waterstate.numwaterplanes = 0;
6050 R_ResetViewRendering2D();
6052 R_Bloom_CopyHDRTexture();
6053 R_Bloom_MakeTexture();
6055 // restore the view settings
6056 r_waterstate.enabled = oldwaterstate;
6057 r_refdef.view.width = oldwidth;
6058 r_refdef.view.height = oldheight;
6059 r_refdef.view.colorscale = oldcolorscale;
6061 R_ResetViewRendering3D();
6063 R_ClearScreen(r_refdef.fogenabled);
6064 if (r_timereport_active)
6065 R_TimeReport("viewclear");
6068 static void R_BlendView(void)
6070 unsigned int permutation;
6071 float uservecs[4][4];
6073 switch (vid.renderpath)
6075 case RENDERPATH_GL20:
6076 case RENDERPATH_D3D9:
6077 case RENDERPATH_D3D10:
6078 case RENDERPATH_D3D11:
6079 case RENDERPATH_SOFT:
6080 case RENDERPATH_GLES2:
6082 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6083 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6084 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6085 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6086 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6088 if (r_bloomstate.texture_screen)
6090 // make sure the buffer is available
6091 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6093 R_ResetViewRendering2D();
6094 R_Mesh_SetMainRenderTargets();
6096 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6098 // declare variables
6100 static float avgspeed;
6102 speed = VectorLength(cl.movement_velocity);
6104 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6105 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6107 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6108 speed = bound(0, speed, 1);
6109 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6111 // calculate values into a standard alpha
6112 cl.motionbluralpha = 1 - exp(-
6114 (r_motionblur.value * speed / 80)
6116 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6119 max(0.0001, cl.time - cl.oldtime) // fps independent
6122 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6123 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6125 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6127 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6128 GL_Color(1, 1, 1, cl.motionbluralpha);
6129 switch(vid.renderpath)
6131 case RENDERPATH_GL11:
6132 case RENDERPATH_GL13:
6133 case RENDERPATH_GL20:
6134 case RENDERPATH_SOFT:
6135 case RENDERPATH_GLES2:
6136 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6138 case RENDERPATH_D3D9:
6139 case RENDERPATH_D3D10:
6140 case RENDERPATH_D3D11:
6141 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6144 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6145 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6146 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6150 // copy view into the screen texture
6151 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);
6152 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6154 else if (!r_bloomstate.texture_bloom)
6156 // we may still have to do view tint...
6157 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6159 // apply a color tint to the whole view
6160 R_ResetViewRendering2D();
6161 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6162 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6163 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6164 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6165 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6167 break; // no screen processing, no bloom, skip it
6170 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6172 // render simple bloom effect
6173 // copy the screen and shrink it and darken it for the bloom process
6174 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6175 // make the bloom texture
6176 R_Bloom_MakeTexture();
6179 #if _MSC_VER >= 1400
6180 #define sscanf sscanf_s
6182 memset(uservecs, 0, sizeof(uservecs));
6183 if (r_glsl_postprocess_uservec1_enable.integer)
6184 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6185 if (r_glsl_postprocess_uservec2_enable.integer)
6186 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6187 if (r_glsl_postprocess_uservec3_enable.integer)
6188 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6189 if (r_glsl_postprocess_uservec4_enable.integer)
6190 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6192 R_ResetViewRendering2D();
6193 GL_Color(1, 1, 1, 1);
6194 GL_BlendFunc(GL_ONE, GL_ZERO);
6196 switch(vid.renderpath)
6198 case RENDERPATH_GL20:
6199 case RENDERPATH_GLES2:
6200 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6201 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6202 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6203 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6204 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6205 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]);
6206 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6207 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]);
6208 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]);
6209 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]);
6210 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]);
6211 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6212 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6213 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);
6215 case RENDERPATH_D3D9:
6217 // 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...
6218 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6219 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6220 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6221 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6222 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6223 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6224 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6225 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6226 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6227 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6228 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6229 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6230 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6231 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6234 case RENDERPATH_D3D10:
6235 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6237 case RENDERPATH_D3D11:
6238 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6240 case RENDERPATH_SOFT:
6241 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6242 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6243 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6244 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6245 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6246 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6247 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6248 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6249 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6250 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6251 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6252 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6253 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6254 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6259 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6260 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6262 case RENDERPATH_GL13:
6263 case RENDERPATH_GL11:
6264 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6266 // apply a color tint to the whole view
6267 R_ResetViewRendering2D();
6268 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6269 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6270 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6271 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6272 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6278 matrix4x4_t r_waterscrollmatrix;
6280 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6282 if (r_refdef.fog_density)
6284 r_refdef.fogcolor[0] = r_refdef.fog_red;
6285 r_refdef.fogcolor[1] = r_refdef.fog_green;
6286 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6288 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6289 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6290 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6291 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6295 VectorCopy(r_refdef.fogcolor, fogvec);
6296 // color.rgb *= ContrastBoost * SceneBrightness;
6297 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6298 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6299 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6300 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6305 void R_UpdateVariables(void)
6309 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6311 r_refdef.farclip = r_farclip_base.value;
6312 if (r_refdef.scene.worldmodel)
6313 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6314 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6316 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6317 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6318 r_refdef.polygonfactor = 0;
6319 r_refdef.polygonoffset = 0;
6320 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6321 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6323 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6324 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6325 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6326 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6327 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6328 if (FAKELIGHT_ENABLED)
6330 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6332 if (r_showsurfaces.integer)
6334 r_refdef.scene.rtworld = false;
6335 r_refdef.scene.rtworldshadows = false;
6336 r_refdef.scene.rtdlight = false;
6337 r_refdef.scene.rtdlightshadows = false;
6338 r_refdef.lightmapintensity = 0;
6341 if (gamemode == GAME_NEHAHRA)
6343 if (gl_fogenable.integer)
6345 r_refdef.oldgl_fogenable = true;
6346 r_refdef.fog_density = gl_fogdensity.value;
6347 r_refdef.fog_red = gl_fogred.value;
6348 r_refdef.fog_green = gl_foggreen.value;
6349 r_refdef.fog_blue = gl_fogblue.value;
6350 r_refdef.fog_alpha = 1;
6351 r_refdef.fog_start = 0;
6352 r_refdef.fog_end = gl_skyclip.value;
6353 r_refdef.fog_height = 1<<30;
6354 r_refdef.fog_fadedepth = 128;
6356 else if (r_refdef.oldgl_fogenable)
6358 r_refdef.oldgl_fogenable = false;
6359 r_refdef.fog_density = 0;
6360 r_refdef.fog_red = 0;
6361 r_refdef.fog_green = 0;
6362 r_refdef.fog_blue = 0;
6363 r_refdef.fog_alpha = 0;
6364 r_refdef.fog_start = 0;
6365 r_refdef.fog_end = 0;
6366 r_refdef.fog_height = 1<<30;
6367 r_refdef.fog_fadedepth = 128;
6371 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6372 r_refdef.fog_start = max(0, r_refdef.fog_start);
6373 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6375 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6377 if (r_refdef.fog_density && r_drawfog.integer)
6379 r_refdef.fogenabled = true;
6380 // this is the point where the fog reaches 0.9986 alpha, which we
6381 // consider a good enough cutoff point for the texture
6382 // (0.9986 * 256 == 255.6)
6383 if (r_fog_exp2.integer)
6384 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6386 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6387 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6388 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6389 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6390 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6391 R_BuildFogHeightTexture();
6392 // fog color was already set
6393 // update the fog texture
6394 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)
6395 R_BuildFogTexture();
6396 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6397 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6400 r_refdef.fogenabled = false;
6402 switch(vid.renderpath)
6404 case RENDERPATH_GL20:
6405 case RENDERPATH_D3D9:
6406 case RENDERPATH_D3D10:
6407 case RENDERPATH_D3D11:
6408 case RENDERPATH_SOFT:
6409 case RENDERPATH_GLES2:
6410 if(v_glslgamma.integer && !vid_gammatables_trivial)
6412 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6414 // build GLSL gamma texture
6415 #define RAMPWIDTH 256
6416 unsigned short ramp[RAMPWIDTH * 3];
6417 unsigned char rampbgr[RAMPWIDTH][4];
6420 r_texture_gammaramps_serial = vid_gammatables_serial;
6422 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6423 for(i = 0; i < RAMPWIDTH; ++i)
6425 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6426 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6427 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6430 if (r_texture_gammaramps)
6432 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6436 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6442 // remove GLSL gamma texture
6445 case RENDERPATH_GL13:
6446 case RENDERPATH_GL11:
6451 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6452 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6458 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6459 if( scenetype != r_currentscenetype ) {
6460 // store the old scenetype
6461 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6462 r_currentscenetype = scenetype;
6463 // move in the new scene
6464 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6473 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6475 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6476 if( scenetype == r_currentscenetype ) {
6477 return &r_refdef.scene;
6479 return &r_scenes_store[ scenetype ];
6488 int dpsoftrast_test;
6489 void R_RenderView(void)
6491 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6493 dpsoftrast_test = r_test.integer;
6495 if (r_timereport_active)
6496 R_TimeReport("start");
6497 r_textureframe++; // used only by R_GetCurrentTexture
6498 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6500 if(R_CompileShader_CheckStaticParms())
6503 if (!r_drawentities.integer)
6504 r_refdef.scene.numentities = 0;
6506 R_AnimCache_ClearCache();
6507 R_FrameData_NewFrame();
6509 /* adjust for stereo display */
6510 if(R_Stereo_Active())
6512 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);
6513 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6516 if (r_refdef.view.isoverlay)
6518 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6519 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6520 R_TimeReport("depthclear");
6522 r_refdef.view.showdebug = false;
6524 r_waterstate.enabled = false;
6525 r_waterstate.numwaterplanes = 0;
6529 r_refdef.view.matrix = originalmatrix;
6535 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6537 r_refdef.view.matrix = originalmatrix;
6538 return; //Host_Error ("R_RenderView: NULL worldmodel");
6541 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6543 R_RenderView_UpdateViewVectors();
6545 R_Shadow_UpdateWorldLightSelection();
6547 R_Bloom_StartFrame();
6548 R_Water_StartFrame();
6551 if (r_timereport_active)
6552 R_TimeReport("viewsetup");
6554 R_ResetViewRendering3D();
6556 if (r_refdef.view.clear || r_refdef.fogenabled)
6558 R_ClearScreen(r_refdef.fogenabled);
6559 if (r_timereport_active)
6560 R_TimeReport("viewclear");
6562 r_refdef.view.clear = true;
6564 // this produces a bloom texture to be used in R_BlendView() later
6565 if (r_bloomstate.hdr)
6567 R_HDR_RenderBloomTexture();
6568 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6569 r_textureframe++; // used only by R_GetCurrentTexture
6572 r_refdef.view.showdebug = true;
6575 if (r_timereport_active)
6576 R_TimeReport("visibility");
6578 r_waterstate.numwaterplanes = 0;
6579 if (r_waterstate.enabled)
6580 R_RenderWaterPlanes();
6583 r_waterstate.numwaterplanes = 0;
6586 if (r_timereport_active)
6587 R_TimeReport("blendview");
6589 GL_Scissor(0, 0, vid.width, vid.height);
6590 GL_ScissorTest(false);
6592 r_refdef.view.matrix = originalmatrix;
6597 void R_RenderWaterPlanes(void)
6599 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6601 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6602 if (r_timereport_active)
6603 R_TimeReport("waterworld");
6606 // don't let sound skip if going slow
6607 if (r_refdef.scene.extraupdate)
6610 R_DrawModelsAddWaterPlanes();
6611 if (r_timereport_active)
6612 R_TimeReport("watermodels");
6614 if (r_waterstate.numwaterplanes)
6616 R_Water_ProcessPlanes();
6617 if (r_timereport_active)
6618 R_TimeReport("waterscenes");
6622 extern void R_DrawLightningBeams (void);
6623 extern void VM_CL_AddPolygonsToMeshQueue (void);
6624 extern void R_DrawPortals (void);
6625 extern cvar_t cl_locs_show;
6626 static void R_DrawLocs(void);
6627 static void R_DrawEntityBBoxes(void);
6628 static void R_DrawModelDecals(void);
6629 extern void R_DrawModelShadows(void);
6630 extern void R_DrawModelShadowMaps(void);
6631 extern cvar_t cl_decals_newsystem;
6632 extern qboolean r_shadow_usingdeferredprepass;
6633 void R_RenderScene(void)
6635 qboolean shadowmapping = false;
6637 if (r_timereport_active)
6638 R_TimeReport("beginscene");
6640 r_refdef.stats.renders++;
6644 // don't let sound skip if going slow
6645 if (r_refdef.scene.extraupdate)
6648 R_MeshQueue_BeginScene();
6652 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);
6654 if (r_timereport_active)
6655 R_TimeReport("skystartframe");
6657 if (cl.csqc_vidvars.drawworld)
6659 // don't let sound skip if going slow
6660 if (r_refdef.scene.extraupdate)
6663 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6665 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6666 if (r_timereport_active)
6667 R_TimeReport("worldsky");
6670 if (R_DrawBrushModelsSky() && r_timereport_active)
6671 R_TimeReport("bmodelsky");
6673 if (skyrendermasked && skyrenderlater)
6675 // we have to force off the water clipping plane while rendering sky
6679 if (r_timereport_active)
6680 R_TimeReport("sky");
6684 R_AnimCache_CacheVisibleEntities();
6685 if (r_timereport_active)
6686 R_TimeReport("animation");
6688 R_Shadow_PrepareLights();
6689 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6690 R_Shadow_PrepareModelShadows();
6691 if (r_timereport_active)
6692 R_TimeReport("preparelights");
6694 if (R_Shadow_ShadowMappingEnabled())
6695 shadowmapping = true;
6697 if (r_shadow_usingdeferredprepass)
6698 R_Shadow_DrawPrepass();
6700 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6702 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6703 if (r_timereport_active)
6704 R_TimeReport("worlddepth");
6706 if (r_depthfirst.integer >= 2)
6708 R_DrawModelsDepth();
6709 if (r_timereport_active)
6710 R_TimeReport("modeldepth");
6713 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6715 R_DrawModelShadowMaps();
6716 R_ResetViewRendering3D();
6717 // don't let sound skip if going slow
6718 if (r_refdef.scene.extraupdate)
6722 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6724 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6725 if (r_timereport_active)
6726 R_TimeReport("world");
6729 // don't let sound skip if going slow
6730 if (r_refdef.scene.extraupdate)
6734 if (r_timereport_active)
6735 R_TimeReport("models");
6737 // don't let sound skip if going slow
6738 if (r_refdef.scene.extraupdate)
6741 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6743 R_DrawModelShadows();
6744 R_ResetViewRendering3D();
6745 // don't let sound skip if going slow
6746 if (r_refdef.scene.extraupdate)
6750 if (!r_shadow_usingdeferredprepass)
6752 R_Shadow_DrawLights();
6753 if (r_timereport_active)
6754 R_TimeReport("rtlights");
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 (cl.csqc_vidvars.drawworld)
6772 if (cl_decals_newsystem.integer)
6774 R_DrawModelDecals();
6775 if (r_timereport_active)
6776 R_TimeReport("modeldecals");
6781 if (r_timereport_active)
6782 R_TimeReport("decals");
6786 if (r_timereport_active)
6787 R_TimeReport("particles");
6790 if (r_timereport_active)
6791 R_TimeReport("explosions");
6793 R_DrawLightningBeams();
6794 if (r_timereport_active)
6795 R_TimeReport("lightning");
6798 VM_CL_AddPolygonsToMeshQueue();
6800 if (r_refdef.view.showdebug)
6802 if (cl_locs_show.integer)
6805 if (r_timereport_active)
6806 R_TimeReport("showlocs");
6809 if (r_drawportals.integer)
6812 if (r_timereport_active)
6813 R_TimeReport("portals");
6816 if (r_showbboxes.value > 0)
6818 R_DrawEntityBBoxes();
6819 if (r_timereport_active)
6820 R_TimeReport("bboxes");
6824 R_MeshQueue_RenderTransparent();
6825 if (r_timereport_active)
6826 R_TimeReport("drawtrans");
6828 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))
6830 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6831 if (r_timereport_active)
6832 R_TimeReport("worlddebug");
6833 R_DrawModelsDebug();
6834 if (r_timereport_active)
6835 R_TimeReport("modeldebug");
6838 if (cl.csqc_vidvars.drawworld)
6840 R_Shadow_DrawCoronas();
6841 if (r_timereport_active)
6842 R_TimeReport("coronas");
6847 GL_DepthTest(false);
6848 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6849 GL_Color(1, 1, 1, 1);
6850 qglBegin(GL_POLYGON);
6851 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6852 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6853 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6854 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6856 qglBegin(GL_POLYGON);
6857 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]);
6858 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]);
6859 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]);
6860 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]);
6862 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6866 // don't let sound skip if going slow
6867 if (r_refdef.scene.extraupdate)
6870 R_ResetViewRendering2D();
6873 static const unsigned short bboxelements[36] =
6883 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6886 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6888 RSurf_ActiveWorldEntity();
6890 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6891 GL_DepthMask(false);
6892 GL_DepthRange(0, 1);
6893 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6894 // R_Mesh_ResetTextureState();
6896 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6897 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6898 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6899 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6900 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6901 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6902 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6903 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6904 R_FillColors(color4f, 8, cr, cg, cb, ca);
6905 if (r_refdef.fogenabled)
6907 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6909 f1 = RSurf_FogVertex(v);
6911 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6912 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6913 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6916 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6917 R_Mesh_ResetTextureState();
6918 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6919 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6922 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6926 prvm_edict_t *edict;
6927 prvm_prog_t *prog_save = prog;
6929 // this function draws bounding boxes of server entities
6933 GL_CullFace(GL_NONE);
6934 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6938 for (i = 0;i < numsurfaces;i++)
6940 edict = PRVM_EDICT_NUM(surfacelist[i]);
6941 switch ((int)edict->fields.server->solid)
6943 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
6944 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
6945 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
6946 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6947 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
6948 default: Vector4Set(color, 0, 0, 0, 0.50);break;
6950 color[3] *= r_showbboxes.value;
6951 color[3] = bound(0, color[3], 1);
6952 GL_DepthTest(!r_showdisabledepthtest.integer);
6953 GL_CullFace(r_refdef.view.cullface_front);
6954 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6960 static void R_DrawEntityBBoxes(void)
6963 prvm_edict_t *edict;
6965 prvm_prog_t *prog_save = prog;
6967 // this function draws bounding boxes of server entities
6973 for (i = 0;i < prog->num_edicts;i++)
6975 edict = PRVM_EDICT_NUM(i);
6976 if (edict->priv.server->free)
6978 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6979 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
6981 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
6983 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
6984 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
6990 static const int nomodelelement3i[24] =
7002 static const unsigned short nomodelelement3s[24] =
7014 static const float nomodelvertex3f[6*3] =
7024 static const float nomodelcolor4f[6*4] =
7026 0.0f, 0.0f, 0.5f, 1.0f,
7027 0.0f, 0.0f, 0.5f, 1.0f,
7028 0.0f, 0.5f, 0.0f, 1.0f,
7029 0.0f, 0.5f, 0.0f, 1.0f,
7030 0.5f, 0.0f, 0.0f, 1.0f,
7031 0.5f, 0.0f, 0.0f, 1.0f
7034 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7040 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);
7042 // this is only called once per entity so numsurfaces is always 1, and
7043 // surfacelist is always {0}, so this code does not handle batches
7045 if (rsurface.ent_flags & RENDER_ADDITIVE)
7047 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7048 GL_DepthMask(false);
7050 else if (rsurface.colormod[3] < 1)
7052 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7053 GL_DepthMask(false);
7057 GL_BlendFunc(GL_ONE, GL_ZERO);
7060 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7061 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7062 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7063 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7064 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7065 for (i = 0, c = color4f;i < 6;i++, c += 4)
7067 c[0] *= rsurface.colormod[0];
7068 c[1] *= rsurface.colormod[1];
7069 c[2] *= rsurface.colormod[2];
7070 c[3] *= rsurface.colormod[3];
7072 if (r_refdef.fogenabled)
7074 for (i = 0, c = color4f;i < 6;i++, c += 4)
7076 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7078 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7079 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7080 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7083 // R_Mesh_ResetTextureState();
7084 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7085 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7086 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7089 void R_DrawNoModel(entity_render_t *ent)
7092 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7093 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7094 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7096 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7099 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7101 vec3_t right1, right2, diff, normal;
7103 VectorSubtract (org2, org1, normal);
7105 // calculate 'right' vector for start
7106 VectorSubtract (r_refdef.view.origin, org1, diff);
7107 CrossProduct (normal, diff, right1);
7108 VectorNormalize (right1);
7110 // calculate 'right' vector for end
7111 VectorSubtract (r_refdef.view.origin, org2, diff);
7112 CrossProduct (normal, diff, right2);
7113 VectorNormalize (right2);
7115 vert[ 0] = org1[0] + width * right1[0];
7116 vert[ 1] = org1[1] + width * right1[1];
7117 vert[ 2] = org1[2] + width * right1[2];
7118 vert[ 3] = org1[0] - width * right1[0];
7119 vert[ 4] = org1[1] - width * right1[1];
7120 vert[ 5] = org1[2] - width * right1[2];
7121 vert[ 6] = org2[0] - width * right2[0];
7122 vert[ 7] = org2[1] - width * right2[1];
7123 vert[ 8] = org2[2] - width * right2[2];
7124 vert[ 9] = org2[0] + width * right2[0];
7125 vert[10] = org2[1] + width * right2[1];
7126 vert[11] = org2[2] + width * right2[2];
7129 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)
7131 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7132 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7133 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7134 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7135 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7136 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7137 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7138 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7139 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7140 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7141 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7142 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7145 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7150 VectorSet(v, x, y, z);
7151 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7152 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7154 if (i == mesh->numvertices)
7156 if (mesh->numvertices < mesh->maxvertices)
7158 VectorCopy(v, vertex3f);
7159 mesh->numvertices++;
7161 return mesh->numvertices;
7167 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7171 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7172 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7173 e = mesh->element3i + mesh->numtriangles * 3;
7174 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7176 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7177 if (mesh->numtriangles < mesh->maxtriangles)
7182 mesh->numtriangles++;
7184 element[1] = element[2];
7188 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7192 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7193 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7194 e = mesh->element3i + mesh->numtriangles * 3;
7195 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7197 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7198 if (mesh->numtriangles < mesh->maxtriangles)
7203 mesh->numtriangles++;
7205 element[1] = element[2];
7209 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7210 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7212 int planenum, planenum2;
7215 mplane_t *plane, *plane2;
7217 double temppoints[2][256*3];
7218 // figure out how large a bounding box we need to properly compute this brush
7220 for (w = 0;w < numplanes;w++)
7221 maxdist = max(maxdist, fabs(planes[w].dist));
7222 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7223 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7224 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7228 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7229 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7231 if (planenum2 == planenum)
7233 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);
7236 if (tempnumpoints < 3)
7238 // generate elements forming a triangle fan for this polygon
7239 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7243 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)
7245 texturelayer_t *layer;
7246 layer = t->currentlayers + t->currentnumlayers++;
7248 layer->depthmask = depthmask;
7249 layer->blendfunc1 = blendfunc1;
7250 layer->blendfunc2 = blendfunc2;
7251 layer->texture = texture;
7252 layer->texmatrix = *matrix;
7253 layer->color[0] = r;
7254 layer->color[1] = g;
7255 layer->color[2] = b;
7256 layer->color[3] = a;
7259 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7261 if(parms[0] == 0 && parms[1] == 0)
7263 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7264 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7269 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7272 index = parms[2] + r_refdef.scene.time * parms[3];
7273 index -= floor(index);
7274 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7277 case Q3WAVEFUNC_NONE:
7278 case Q3WAVEFUNC_NOISE:
7279 case Q3WAVEFUNC_COUNT:
7282 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7283 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7284 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7285 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7286 case Q3WAVEFUNC_TRIANGLE:
7288 f = index - floor(index);
7299 f = parms[0] + parms[1] * f;
7300 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7301 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7305 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7310 matrix4x4_t matrix, temp;
7311 switch(tcmod->tcmod)
7315 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7316 matrix = r_waterscrollmatrix;
7318 matrix = identitymatrix;
7320 case Q3TCMOD_ENTITYTRANSLATE:
7321 // this is used in Q3 to allow the gamecode to control texcoord
7322 // scrolling on the entity, which is not supported in darkplaces yet.
7323 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7325 case Q3TCMOD_ROTATE:
7326 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7327 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7328 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7331 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7333 case Q3TCMOD_SCROLL:
7334 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7336 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7337 w = (int) tcmod->parms[0];
7338 h = (int) tcmod->parms[1];
7339 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7341 idx = (int) floor(f * w * h);
7342 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7344 case Q3TCMOD_STRETCH:
7345 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7346 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7348 case Q3TCMOD_TRANSFORM:
7349 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7350 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7351 VectorSet(tcmat + 6, 0 , 0 , 1);
7352 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7353 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7355 case Q3TCMOD_TURBULENT:
7356 // this is handled in the RSurf_PrepareVertices function
7357 matrix = identitymatrix;
7361 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7364 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7366 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7367 char name[MAX_QPATH];
7368 skinframe_t *skinframe;
7369 unsigned char pixels[296*194];
7370 strlcpy(cache->name, skinname, sizeof(cache->name));
7371 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7372 if (developer_loading.integer)
7373 Con_Printf("loading %s\n", name);
7374 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7375 if (!skinframe || !skinframe->base)
7378 fs_offset_t filesize;
7380 f = FS_LoadFile(name, tempmempool, true, &filesize);
7383 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7384 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7388 cache->skinframe = skinframe;
7391 texture_t *R_GetCurrentTexture(texture_t *t)
7394 const entity_render_t *ent = rsurface.entity;
7395 dp_model_t *model = ent->model;
7396 q3shaderinfo_layer_tcmod_t *tcmod;
7398 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7399 return t->currentframe;
7400 t->update_lastrenderframe = r_textureframe;
7401 t->update_lastrenderentity = (void *)ent;
7403 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7404 t->camera_entity = ent->entitynumber;
7406 t->camera_entity = 0;
7408 // switch to an alternate material if this is a q1bsp animated material
7410 texture_t *texture = t;
7411 int s = rsurface.ent_skinnum;
7412 if ((unsigned int)s >= (unsigned int)model->numskins)
7414 if (model->skinscenes)
7416 if (model->skinscenes[s].framecount > 1)
7417 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7419 s = model->skinscenes[s].firstframe;
7422 t = t + s * model->num_surfaces;
7425 // use an alternate animation if the entity's frame is not 0,
7426 // and only if the texture has an alternate animation
7427 if (rsurface.ent_alttextures && t->anim_total[1])
7428 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7430 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7432 texture->currentframe = t;
7435 // update currentskinframe to be a qw skin or animation frame
7436 if (rsurface.ent_qwskin >= 0)
7438 i = rsurface.ent_qwskin;
7439 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7441 r_qwskincache_size = cl.maxclients;
7443 Mem_Free(r_qwskincache);
7444 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7446 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7447 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7448 t->currentskinframe = r_qwskincache[i].skinframe;
7449 if (t->currentskinframe == NULL)
7450 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7452 else if (t->numskinframes >= 2)
7453 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7454 if (t->backgroundnumskinframes >= 2)
7455 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7457 t->currentmaterialflags = t->basematerialflags;
7458 t->currentalpha = rsurface.colormod[3];
7459 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7460 t->currentalpha *= r_wateralpha.value;
7461 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7462 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7463 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7464 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7465 if (!(rsurface.ent_flags & RENDER_LIGHT))
7466 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7467 else if (FAKELIGHT_ENABLED)
7469 // no modellight if using fakelight for the map
7471 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7473 // pick a model lighting mode
7474 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7475 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7477 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7479 if (rsurface.ent_flags & RENDER_ADDITIVE)
7480 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7481 else if (t->currentalpha < 1)
7482 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7483 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7484 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7485 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7486 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7487 if (t->backgroundnumskinframes)
7488 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7489 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7491 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7492 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7495 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7496 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7497 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7499 // there is no tcmod
7500 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7502 t->currenttexmatrix = r_waterscrollmatrix;
7503 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7505 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7507 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7508 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7511 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7512 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7513 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7514 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7516 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7517 if (t->currentskinframe->qpixels)
7518 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7519 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7520 if (!t->basetexture)
7521 t->basetexture = r_texture_notexture;
7522 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7523 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7524 t->nmaptexture = t->currentskinframe->nmap;
7525 if (!t->nmaptexture)
7526 t->nmaptexture = r_texture_blanknormalmap;
7527 t->glosstexture = r_texture_black;
7528 t->glowtexture = t->currentskinframe->glow;
7529 t->fogtexture = t->currentskinframe->fog;
7530 t->reflectmasktexture = t->currentskinframe->reflect;
7531 if (t->backgroundnumskinframes)
7533 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7534 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7535 t->backgroundglosstexture = r_texture_black;
7536 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7537 if (!t->backgroundnmaptexture)
7538 t->backgroundnmaptexture = r_texture_blanknormalmap;
7542 t->backgroundbasetexture = r_texture_white;
7543 t->backgroundnmaptexture = r_texture_blanknormalmap;
7544 t->backgroundglosstexture = r_texture_black;
7545 t->backgroundglowtexture = NULL;
7547 t->specularpower = r_shadow_glossexponent.value;
7548 // TODO: store reference values for these in the texture?
7549 t->specularscale = 0;
7550 if (r_shadow_gloss.integer > 0)
7552 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7554 if (r_shadow_glossintensity.value > 0)
7556 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7557 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7558 t->specularscale = r_shadow_glossintensity.value;
7561 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7563 t->glosstexture = r_texture_white;
7564 t->backgroundglosstexture = r_texture_white;
7565 t->specularscale = r_shadow_gloss2intensity.value;
7566 t->specularpower = r_shadow_gloss2exponent.value;
7569 t->specularscale *= t->specularscalemod;
7570 t->specularpower *= t->specularpowermod;
7572 // lightmaps mode looks bad with dlights using actual texturing, so turn
7573 // off the colormap and glossmap, but leave the normalmap on as it still
7574 // accurately represents the shading involved
7575 if (gl_lightmaps.integer)
7577 t->basetexture = r_texture_grey128;
7578 t->pantstexture = r_texture_black;
7579 t->shirttexture = r_texture_black;
7580 t->nmaptexture = r_texture_blanknormalmap;
7581 t->glosstexture = r_texture_black;
7582 t->glowtexture = NULL;
7583 t->fogtexture = NULL;
7584 t->reflectmasktexture = NULL;
7585 t->backgroundbasetexture = NULL;
7586 t->backgroundnmaptexture = r_texture_blanknormalmap;
7587 t->backgroundglosstexture = r_texture_black;
7588 t->backgroundglowtexture = NULL;
7589 t->specularscale = 0;
7590 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7593 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7594 VectorClear(t->dlightcolor);
7595 t->currentnumlayers = 0;
7596 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7598 int blendfunc1, blendfunc2;
7600 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7602 blendfunc1 = GL_SRC_ALPHA;
7603 blendfunc2 = GL_ONE;
7605 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7607 blendfunc1 = GL_SRC_ALPHA;
7608 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7610 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7612 blendfunc1 = t->customblendfunc[0];
7613 blendfunc2 = t->customblendfunc[1];
7617 blendfunc1 = GL_ONE;
7618 blendfunc2 = GL_ZERO;
7620 // don't colormod evilblend textures
7621 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7622 VectorSet(t->lightmapcolor, 1, 1, 1);
7623 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7624 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7626 // fullbright is not affected by r_refdef.lightmapintensity
7627 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]);
7628 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7629 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]);
7630 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7631 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]);
7635 vec3_t ambientcolor;
7637 // set the color tint used for lights affecting this surface
7638 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7640 // q3bsp has no lightmap updates, so the lightstylevalue that
7641 // would normally be baked into the lightmap must be
7642 // applied to the color
7643 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7644 if (model->type == mod_brushq3)
7645 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7646 colorscale *= r_refdef.lightmapintensity;
7647 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7648 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7649 // basic lit geometry
7650 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]);
7651 // add pants/shirt if needed
7652 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7653 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]);
7654 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7655 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]);
7656 // now add ambient passes if needed
7657 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7659 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]);
7660 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7661 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]);
7662 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7663 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]);
7666 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7667 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]);
7668 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7670 // if this is opaque use alpha blend which will darken the earlier
7673 // if this is an alpha blended material, all the earlier passes
7674 // were darkened by fog already, so we only need to add the fog
7675 // color ontop through the fog mask texture
7677 // if this is an additive blended material, all the earlier passes
7678 // were darkened by fog already, and we should not add fog color
7679 // (because the background was not darkened, there is no fog color
7680 // that was lost behind it).
7681 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]);
7685 return t->currentframe;
7688 rsurfacestate_t rsurface;
7690 void RSurf_ActiveWorldEntity(void)
7692 dp_model_t *model = r_refdef.scene.worldmodel;
7693 //if (rsurface.entity == r_refdef.scene.worldentity)
7695 rsurface.entity = r_refdef.scene.worldentity;
7696 rsurface.skeleton = NULL;
7697 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7698 rsurface.ent_skinnum = 0;
7699 rsurface.ent_qwskin = -1;
7700 rsurface.ent_shadertime = 0;
7701 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7702 rsurface.matrix = identitymatrix;
7703 rsurface.inversematrix = identitymatrix;
7704 rsurface.matrixscale = 1;
7705 rsurface.inversematrixscale = 1;
7706 R_EntityMatrix(&identitymatrix);
7707 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7708 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7709 rsurface.fograngerecip = r_refdef.fograngerecip;
7710 rsurface.fogheightfade = r_refdef.fogheightfade;
7711 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7712 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7713 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7714 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7715 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7716 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7717 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7718 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7719 rsurface.colormod[3] = 1;
7720 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);
7721 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7722 rsurface.frameblend[0].lerp = 1;
7723 rsurface.ent_alttextures = false;
7724 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7725 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7726 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7727 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7728 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7729 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7730 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7731 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7732 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7733 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7734 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7735 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7736 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7737 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7738 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7739 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7740 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7741 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7742 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7743 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7744 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7745 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7746 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7747 rsurface.modelelement3i = model->surfmesh.data_element3i;
7748 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7749 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7750 rsurface.modelelement3s = model->surfmesh.data_element3s;
7751 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7752 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7753 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7754 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7755 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7756 rsurface.modelsurfaces = model->data_surfaces;
7757 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7758 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7759 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7760 rsurface.modelgeneratedvertex = false;
7761 rsurface.batchgeneratedvertex = false;
7762 rsurface.batchfirstvertex = 0;
7763 rsurface.batchnumvertices = 0;
7764 rsurface.batchfirsttriangle = 0;
7765 rsurface.batchnumtriangles = 0;
7766 rsurface.batchvertex3f = NULL;
7767 rsurface.batchvertex3f_vertexbuffer = NULL;
7768 rsurface.batchvertex3f_bufferoffset = 0;
7769 rsurface.batchsvector3f = NULL;
7770 rsurface.batchsvector3f_vertexbuffer = NULL;
7771 rsurface.batchsvector3f_bufferoffset = 0;
7772 rsurface.batchtvector3f = NULL;
7773 rsurface.batchtvector3f_vertexbuffer = NULL;
7774 rsurface.batchtvector3f_bufferoffset = 0;
7775 rsurface.batchnormal3f = NULL;
7776 rsurface.batchnormal3f_vertexbuffer = NULL;
7777 rsurface.batchnormal3f_bufferoffset = 0;
7778 rsurface.batchlightmapcolor4f = NULL;
7779 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7780 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7781 rsurface.batchtexcoordtexture2f = NULL;
7782 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7783 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7784 rsurface.batchtexcoordlightmap2f = NULL;
7785 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7786 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7787 rsurface.batchvertexmesh = NULL;
7788 rsurface.batchvertexmeshbuffer = NULL;
7789 rsurface.batchvertex3fbuffer = NULL;
7790 rsurface.batchelement3i = NULL;
7791 rsurface.batchelement3i_indexbuffer = NULL;
7792 rsurface.batchelement3i_bufferoffset = 0;
7793 rsurface.batchelement3s = NULL;
7794 rsurface.batchelement3s_indexbuffer = NULL;
7795 rsurface.batchelement3s_bufferoffset = 0;
7796 rsurface.passcolor4f = NULL;
7797 rsurface.passcolor4f_vertexbuffer = NULL;
7798 rsurface.passcolor4f_bufferoffset = 0;
7801 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7803 dp_model_t *model = ent->model;
7804 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7806 rsurface.entity = (entity_render_t *)ent;
7807 rsurface.skeleton = ent->skeleton;
7808 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7809 rsurface.ent_skinnum = ent->skinnum;
7810 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;
7811 rsurface.ent_shadertime = ent->shadertime;
7812 rsurface.ent_flags = ent->flags;
7813 rsurface.matrix = ent->matrix;
7814 rsurface.inversematrix = ent->inversematrix;
7815 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7816 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7817 R_EntityMatrix(&rsurface.matrix);
7818 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7819 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7820 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7821 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7822 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7823 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7824 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7825 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7826 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7827 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7828 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7829 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7830 rsurface.colormod[3] = ent->alpha;
7831 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7832 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7833 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7834 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7835 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7836 if (ent->model->brush.submodel && !prepass)
7838 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7839 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7841 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7843 if (ent->animcache_vertex3f)
7845 rsurface.modelvertex3f = ent->animcache_vertex3f;
7846 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7847 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7848 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7849 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7850 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7851 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7853 else if (wanttangents)
7855 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7856 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7857 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7858 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7859 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7860 rsurface.modelvertexmesh = NULL;
7861 rsurface.modelvertexmeshbuffer = NULL;
7862 rsurface.modelvertex3fbuffer = NULL;
7864 else if (wantnormals)
7866 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7867 rsurface.modelsvector3f = NULL;
7868 rsurface.modeltvector3f = NULL;
7869 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7870 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7871 rsurface.modelvertexmesh = NULL;
7872 rsurface.modelvertexmeshbuffer = NULL;
7873 rsurface.modelvertex3fbuffer = NULL;
7877 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7878 rsurface.modelsvector3f = NULL;
7879 rsurface.modeltvector3f = NULL;
7880 rsurface.modelnormal3f = NULL;
7881 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7882 rsurface.modelvertexmesh = NULL;
7883 rsurface.modelvertexmeshbuffer = NULL;
7884 rsurface.modelvertex3fbuffer = NULL;
7886 rsurface.modelvertex3f_vertexbuffer = 0;
7887 rsurface.modelvertex3f_bufferoffset = 0;
7888 rsurface.modelsvector3f_vertexbuffer = 0;
7889 rsurface.modelsvector3f_bufferoffset = 0;
7890 rsurface.modeltvector3f_vertexbuffer = 0;
7891 rsurface.modeltvector3f_bufferoffset = 0;
7892 rsurface.modelnormal3f_vertexbuffer = 0;
7893 rsurface.modelnormal3f_bufferoffset = 0;
7894 rsurface.modelgeneratedvertex = true;
7898 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7899 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7900 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7901 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7902 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7903 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7904 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7905 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7906 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7907 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7908 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7909 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7910 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7911 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7912 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7913 rsurface.modelgeneratedvertex = false;
7915 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7916 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7917 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7918 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7919 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7920 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7921 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7922 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7923 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7924 rsurface.modelelement3i = model->surfmesh.data_element3i;
7925 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7926 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7927 rsurface.modelelement3s = model->surfmesh.data_element3s;
7928 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7929 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7930 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7931 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7932 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7933 rsurface.modelsurfaces = model->data_surfaces;
7934 rsurface.batchgeneratedvertex = false;
7935 rsurface.batchfirstvertex = 0;
7936 rsurface.batchnumvertices = 0;
7937 rsurface.batchfirsttriangle = 0;
7938 rsurface.batchnumtriangles = 0;
7939 rsurface.batchvertex3f = NULL;
7940 rsurface.batchvertex3f_vertexbuffer = NULL;
7941 rsurface.batchvertex3f_bufferoffset = 0;
7942 rsurface.batchsvector3f = NULL;
7943 rsurface.batchsvector3f_vertexbuffer = NULL;
7944 rsurface.batchsvector3f_bufferoffset = 0;
7945 rsurface.batchtvector3f = NULL;
7946 rsurface.batchtvector3f_vertexbuffer = NULL;
7947 rsurface.batchtvector3f_bufferoffset = 0;
7948 rsurface.batchnormal3f = NULL;
7949 rsurface.batchnormal3f_vertexbuffer = NULL;
7950 rsurface.batchnormal3f_bufferoffset = 0;
7951 rsurface.batchlightmapcolor4f = NULL;
7952 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7953 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7954 rsurface.batchtexcoordtexture2f = NULL;
7955 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7956 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7957 rsurface.batchtexcoordlightmap2f = NULL;
7958 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7959 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7960 rsurface.batchvertexmesh = NULL;
7961 rsurface.batchvertexmeshbuffer = NULL;
7962 rsurface.batchvertex3fbuffer = NULL;
7963 rsurface.batchelement3i = NULL;
7964 rsurface.batchelement3i_indexbuffer = NULL;
7965 rsurface.batchelement3i_bufferoffset = 0;
7966 rsurface.batchelement3s = NULL;
7967 rsurface.batchelement3s_indexbuffer = NULL;
7968 rsurface.batchelement3s_bufferoffset = 0;
7969 rsurface.passcolor4f = NULL;
7970 rsurface.passcolor4f_vertexbuffer = NULL;
7971 rsurface.passcolor4f_bufferoffset = 0;
7974 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)
7976 rsurface.entity = r_refdef.scene.worldentity;
7977 rsurface.skeleton = NULL;
7978 rsurface.ent_skinnum = 0;
7979 rsurface.ent_qwskin = -1;
7980 rsurface.ent_shadertime = shadertime;
7981 rsurface.ent_flags = entflags;
7982 rsurface.modelnumvertices = numvertices;
7983 rsurface.modelnumtriangles = numtriangles;
7984 rsurface.matrix = *matrix;
7985 rsurface.inversematrix = *inversematrix;
7986 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7987 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7988 R_EntityMatrix(&rsurface.matrix);
7989 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7990 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7991 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7992 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7993 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7994 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7995 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7996 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7997 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7998 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7999 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8000 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8001 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);
8002 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8003 rsurface.frameblend[0].lerp = 1;
8004 rsurface.ent_alttextures = false;
8005 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8006 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8009 rsurface.modelvertex3f = (float *)vertex3f;
8010 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8011 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8012 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8014 else if (wantnormals)
8016 rsurface.modelvertex3f = (float *)vertex3f;
8017 rsurface.modelsvector3f = NULL;
8018 rsurface.modeltvector3f = NULL;
8019 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8023 rsurface.modelvertex3f = (float *)vertex3f;
8024 rsurface.modelsvector3f = NULL;
8025 rsurface.modeltvector3f = NULL;
8026 rsurface.modelnormal3f = NULL;
8028 rsurface.modelvertexmesh = NULL;
8029 rsurface.modelvertexmeshbuffer = NULL;
8030 rsurface.modelvertex3fbuffer = NULL;
8031 rsurface.modelvertex3f_vertexbuffer = 0;
8032 rsurface.modelvertex3f_bufferoffset = 0;
8033 rsurface.modelsvector3f_vertexbuffer = 0;
8034 rsurface.modelsvector3f_bufferoffset = 0;
8035 rsurface.modeltvector3f_vertexbuffer = 0;
8036 rsurface.modeltvector3f_bufferoffset = 0;
8037 rsurface.modelnormal3f_vertexbuffer = 0;
8038 rsurface.modelnormal3f_bufferoffset = 0;
8039 rsurface.modelgeneratedvertex = true;
8040 rsurface.modellightmapcolor4f = (float *)color4f;
8041 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8042 rsurface.modellightmapcolor4f_bufferoffset = 0;
8043 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8044 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8045 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8046 rsurface.modeltexcoordlightmap2f = NULL;
8047 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8048 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8049 rsurface.modelelement3i = (int *)element3i;
8050 rsurface.modelelement3i_indexbuffer = NULL;
8051 rsurface.modelelement3i_bufferoffset = 0;
8052 rsurface.modelelement3s = (unsigned short *)element3s;
8053 rsurface.modelelement3s_indexbuffer = NULL;
8054 rsurface.modelelement3s_bufferoffset = 0;
8055 rsurface.modellightmapoffsets = NULL;
8056 rsurface.modelsurfaces = NULL;
8057 rsurface.batchgeneratedvertex = false;
8058 rsurface.batchfirstvertex = 0;
8059 rsurface.batchnumvertices = 0;
8060 rsurface.batchfirsttriangle = 0;
8061 rsurface.batchnumtriangles = 0;
8062 rsurface.batchvertex3f = NULL;
8063 rsurface.batchvertex3f_vertexbuffer = NULL;
8064 rsurface.batchvertex3f_bufferoffset = 0;
8065 rsurface.batchsvector3f = NULL;
8066 rsurface.batchsvector3f_vertexbuffer = NULL;
8067 rsurface.batchsvector3f_bufferoffset = 0;
8068 rsurface.batchtvector3f = NULL;
8069 rsurface.batchtvector3f_vertexbuffer = NULL;
8070 rsurface.batchtvector3f_bufferoffset = 0;
8071 rsurface.batchnormal3f = NULL;
8072 rsurface.batchnormal3f_vertexbuffer = NULL;
8073 rsurface.batchnormal3f_bufferoffset = 0;
8074 rsurface.batchlightmapcolor4f = NULL;
8075 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8076 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8077 rsurface.batchtexcoordtexture2f = NULL;
8078 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8079 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8080 rsurface.batchtexcoordlightmap2f = NULL;
8081 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8082 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8083 rsurface.batchvertexmesh = NULL;
8084 rsurface.batchvertexmeshbuffer = NULL;
8085 rsurface.batchvertex3fbuffer = NULL;
8086 rsurface.batchelement3i = NULL;
8087 rsurface.batchelement3i_indexbuffer = NULL;
8088 rsurface.batchelement3i_bufferoffset = 0;
8089 rsurface.batchelement3s = NULL;
8090 rsurface.batchelement3s_indexbuffer = NULL;
8091 rsurface.batchelement3s_bufferoffset = 0;
8092 rsurface.passcolor4f = NULL;
8093 rsurface.passcolor4f_vertexbuffer = NULL;
8094 rsurface.passcolor4f_bufferoffset = 0;
8096 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8098 if ((wantnormals || wanttangents) && !normal3f)
8100 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8101 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8103 if (wanttangents && !svector3f)
8105 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8106 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8107 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8112 float RSurf_FogPoint(const float *v)
8114 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8115 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8116 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8117 float FogHeightFade = r_refdef.fogheightfade;
8119 unsigned int fogmasktableindex;
8120 if (r_refdef.fogplaneviewabove)
8121 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8123 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8124 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8125 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8128 float RSurf_FogVertex(const float *v)
8130 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8131 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8132 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8133 float FogHeightFade = rsurface.fogheightfade;
8135 unsigned int fogmasktableindex;
8136 if (r_refdef.fogplaneviewabove)
8137 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8139 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8140 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8141 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8144 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8147 for (i = 0;i < numelements;i++)
8148 outelement3i[i] = inelement3i[i] + adjust;
8151 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8152 extern cvar_t gl_vbo;
8153 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8161 int surfacefirsttriangle;
8162 int surfacenumtriangles;
8163 int surfacefirstvertex;
8164 int surfaceendvertex;
8165 int surfacenumvertices;
8166 int batchnumvertices;
8167 int batchnumtriangles;
8171 qboolean dynamicvertex;
8175 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8177 q3shaderinfo_deform_t *deform;
8178 const msurface_t *surface, *firstsurface;
8179 r_vertexmesh_t *vertexmesh;
8180 if (!texturenumsurfaces)
8182 // find vertex range of this surface batch
8184 firstsurface = texturesurfacelist[0];
8185 firsttriangle = firstsurface->num_firsttriangle;
8186 batchnumvertices = 0;
8187 batchnumtriangles = 0;
8188 firstvertex = endvertex = firstsurface->num_firstvertex;
8189 for (i = 0;i < texturenumsurfaces;i++)
8191 surface = texturesurfacelist[i];
8192 if (surface != firstsurface + i)
8194 surfacefirstvertex = surface->num_firstvertex;
8195 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8196 surfacenumvertices = surface->num_vertices;
8197 surfacenumtriangles = surface->num_triangles;
8198 if (firstvertex > surfacefirstvertex)
8199 firstvertex = surfacefirstvertex;
8200 if (endvertex < surfaceendvertex)
8201 endvertex = surfaceendvertex;
8202 batchnumvertices += surfacenumvertices;
8203 batchnumtriangles += surfacenumtriangles;
8206 // we now know the vertex range used, and if there are any gaps in it
8207 rsurface.batchfirstvertex = firstvertex;
8208 rsurface.batchnumvertices = endvertex - firstvertex;
8209 rsurface.batchfirsttriangle = firsttriangle;
8210 rsurface.batchnumtriangles = batchnumtriangles;
8212 // this variable holds flags for which properties have been updated that
8213 // may require regenerating vertexmesh array...
8216 // check if any dynamic vertex processing must occur
8217 dynamicvertex = false;
8219 // if there is a chance of animated vertex colors, it's a dynamic batch
8220 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8222 dynamicvertex = true;
8223 batchneed |= BATCHNEED_NOGAPS;
8224 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8227 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8229 switch (deform->deform)
8232 case Q3DEFORM_PROJECTIONSHADOW:
8233 case Q3DEFORM_TEXT0:
8234 case Q3DEFORM_TEXT1:
8235 case Q3DEFORM_TEXT2:
8236 case Q3DEFORM_TEXT3:
8237 case Q3DEFORM_TEXT4:
8238 case Q3DEFORM_TEXT5:
8239 case Q3DEFORM_TEXT6:
8240 case Q3DEFORM_TEXT7:
8243 case Q3DEFORM_AUTOSPRITE:
8244 dynamicvertex = true;
8245 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8246 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8248 case Q3DEFORM_AUTOSPRITE2:
8249 dynamicvertex = true;
8250 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8251 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8253 case Q3DEFORM_NORMAL:
8254 dynamicvertex = true;
8255 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8256 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8259 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8260 break; // if wavefunc is a nop, ignore this transform
8261 dynamicvertex = true;
8262 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8263 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8265 case Q3DEFORM_BULGE:
8266 dynamicvertex = true;
8267 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8268 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8271 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8272 break; // if wavefunc is a nop, ignore this transform
8273 dynamicvertex = true;
8274 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8275 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8279 switch(rsurface.texture->tcgen.tcgen)
8282 case Q3TCGEN_TEXTURE:
8284 case Q3TCGEN_LIGHTMAP:
8285 dynamicvertex = true;
8286 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8287 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8289 case Q3TCGEN_VECTOR:
8290 dynamicvertex = true;
8291 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8292 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8294 case Q3TCGEN_ENVIRONMENT:
8295 dynamicvertex = true;
8296 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8297 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8300 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8302 dynamicvertex = true;
8303 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8304 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8307 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8309 dynamicvertex = true;
8310 batchneed |= BATCHNEED_NOGAPS;
8311 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8314 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8316 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8317 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8318 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8319 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8320 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8321 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8322 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8325 // when the model data has no vertex buffer (dynamic mesh), we need to
8327 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8328 batchneed |= BATCHNEED_NOGAPS;
8330 // if needsupdate, we have to do a dynamic vertex batch for sure
8331 if (needsupdate & batchneed)
8332 dynamicvertex = true;
8334 // see if we need to build vertexmesh from arrays
8335 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8336 dynamicvertex = true;
8338 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8339 // also some drivers strongly dislike firstvertex
8340 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8341 dynamicvertex = true;
8343 rsurface.batchvertex3f = rsurface.modelvertex3f;
8344 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8345 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8346 rsurface.batchsvector3f = rsurface.modelsvector3f;
8347 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8348 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8349 rsurface.batchtvector3f = rsurface.modeltvector3f;
8350 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8351 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8352 rsurface.batchnormal3f = rsurface.modelnormal3f;
8353 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8354 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8355 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8356 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8357 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8358 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8359 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8360 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8361 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8362 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8363 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8364 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8365 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8366 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8367 rsurface.batchelement3i = rsurface.modelelement3i;
8368 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8369 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8370 rsurface.batchelement3s = rsurface.modelelement3s;
8371 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8372 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8374 // if any dynamic vertex processing has to occur in software, we copy the
8375 // entire surface list together before processing to rebase the vertices
8376 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8378 // if any gaps exist and we do not have a static vertex buffer, we have to
8379 // copy the surface list together to avoid wasting upload bandwidth on the
8380 // vertices in the gaps.
8382 // if gaps exist and we have a static vertex buffer, we still have to
8383 // combine the index buffer ranges into one dynamic index buffer.
8385 // in all cases we end up with data that can be drawn in one call.
8389 // static vertex data, just set pointers...
8390 rsurface.batchgeneratedvertex = false;
8391 // if there are gaps, we want to build a combined index buffer,
8392 // otherwise use the original static buffer with an appropriate offset
8395 // build a new triangle elements array for this batch
8396 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8397 rsurface.batchfirsttriangle = 0;
8399 for (i = 0;i < texturenumsurfaces;i++)
8401 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8402 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8403 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8404 numtriangles += surfacenumtriangles;
8406 rsurface.batchelement3i_indexbuffer = NULL;
8407 rsurface.batchelement3i_bufferoffset = 0;
8408 rsurface.batchelement3s = NULL;
8409 rsurface.batchelement3s_indexbuffer = NULL;
8410 rsurface.batchelement3s_bufferoffset = 0;
8411 if (endvertex <= 65536)
8413 // make a 16bit (unsigned short) index array if possible
8414 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8415 for (i = 0;i < numtriangles*3;i++)
8416 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8422 // something needs software processing, do it for real...
8423 // we only directly handle separate array data in this case and then
8424 // generate interleaved data if needed...
8425 rsurface.batchgeneratedvertex = true;
8427 // now copy the vertex data into a combined array and make an index array
8428 // (this is what Quake3 does all the time)
8429 //if (gaps || rsurface.batchfirstvertex)
8431 rsurface.batchvertex3fbuffer = NULL;
8432 rsurface.batchvertexmesh = NULL;
8433 rsurface.batchvertexmeshbuffer = NULL;
8434 rsurface.batchvertex3f = NULL;
8435 rsurface.batchvertex3f_vertexbuffer = NULL;
8436 rsurface.batchvertex3f_bufferoffset = 0;
8437 rsurface.batchsvector3f = NULL;
8438 rsurface.batchsvector3f_vertexbuffer = NULL;
8439 rsurface.batchsvector3f_bufferoffset = 0;
8440 rsurface.batchtvector3f = NULL;
8441 rsurface.batchtvector3f_vertexbuffer = NULL;
8442 rsurface.batchtvector3f_bufferoffset = 0;
8443 rsurface.batchnormal3f = NULL;
8444 rsurface.batchnormal3f_vertexbuffer = NULL;
8445 rsurface.batchnormal3f_bufferoffset = 0;
8446 rsurface.batchlightmapcolor4f = NULL;
8447 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8448 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8449 rsurface.batchtexcoordtexture2f = NULL;
8450 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8451 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8452 rsurface.batchtexcoordlightmap2f = NULL;
8453 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8454 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8455 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8456 rsurface.batchelement3i_indexbuffer = NULL;
8457 rsurface.batchelement3i_bufferoffset = 0;
8458 rsurface.batchelement3s = NULL;
8459 rsurface.batchelement3s_indexbuffer = NULL;
8460 rsurface.batchelement3s_bufferoffset = 0;
8461 // we'll only be setting up certain arrays as needed
8462 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8463 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8464 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8465 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8466 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8467 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8468 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8470 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8471 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8473 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8474 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8475 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8476 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8477 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8478 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8481 for (i = 0;i < texturenumsurfaces;i++)
8483 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8484 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8485 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8486 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8487 // copy only the data requested
8488 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8489 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8490 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8492 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8493 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8494 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8495 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8496 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8498 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8499 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8501 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8502 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8503 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8504 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8505 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8506 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8508 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8509 numvertices += surfacenumvertices;
8510 numtriangles += surfacenumtriangles;
8513 // generate a 16bit index array as well if possible
8514 // (in general, dynamic batches fit)
8515 if (numvertices <= 65536)
8517 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8518 for (i = 0;i < numtriangles*3;i++)
8519 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8522 // since we've copied everything, the batch now starts at 0
8523 rsurface.batchfirstvertex = 0;
8524 rsurface.batchnumvertices = batchnumvertices;
8525 rsurface.batchfirsttriangle = 0;
8526 rsurface.batchnumtriangles = batchnumtriangles;
8529 // q1bsp surfaces rendered in vertex color mode have to have colors
8530 // calculated based on lightstyles
8531 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8533 // generate color arrays for the surfaces in this list
8538 const unsigned char *lm;
8539 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8540 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8541 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8543 for (i = 0;i < texturenumsurfaces;i++)
8545 surface = texturesurfacelist[i];
8546 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8547 surfacenumvertices = surface->num_vertices;
8548 if (surface->lightmapinfo->samples)
8550 for (j = 0;j < surfacenumvertices;j++)
8552 lm = surface->lightmapinfo->samples + offsets[j];
8553 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8554 VectorScale(lm, scale, c);
8555 if (surface->lightmapinfo->styles[1] != 255)
8557 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8559 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8560 VectorMA(c, scale, lm, c);
8561 if (surface->lightmapinfo->styles[2] != 255)
8564 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8565 VectorMA(c, scale, lm, c);
8566 if (surface->lightmapinfo->styles[3] != 255)
8569 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8570 VectorMA(c, scale, lm, c);
8577 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);
8583 for (j = 0;j < surfacenumvertices;j++)
8585 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8592 // if vertices are deformed (sprite flares and things in maps, possibly
8593 // water waves, bulges and other deformations), modify the copied vertices
8595 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8597 switch (deform->deform)
8600 case Q3DEFORM_PROJECTIONSHADOW:
8601 case Q3DEFORM_TEXT0:
8602 case Q3DEFORM_TEXT1:
8603 case Q3DEFORM_TEXT2:
8604 case Q3DEFORM_TEXT3:
8605 case Q3DEFORM_TEXT4:
8606 case Q3DEFORM_TEXT5:
8607 case Q3DEFORM_TEXT6:
8608 case Q3DEFORM_TEXT7:
8611 case Q3DEFORM_AUTOSPRITE:
8612 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8613 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8614 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8615 VectorNormalize(newforward);
8616 VectorNormalize(newright);
8617 VectorNormalize(newup);
8618 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8619 // rsurface.batchvertex3f_vertexbuffer = NULL;
8620 // rsurface.batchvertex3f_bufferoffset = 0;
8621 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8622 // rsurface.batchsvector3f_vertexbuffer = NULL;
8623 // rsurface.batchsvector3f_bufferoffset = 0;
8624 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8625 // rsurface.batchtvector3f_vertexbuffer = NULL;
8626 // rsurface.batchtvector3f_bufferoffset = 0;
8627 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8628 // rsurface.batchnormal3f_vertexbuffer = NULL;
8629 // rsurface.batchnormal3f_bufferoffset = 0;
8630 // a single autosprite surface can contain multiple sprites...
8631 for (j = 0;j < batchnumvertices - 3;j += 4)
8633 VectorClear(center);
8634 for (i = 0;i < 4;i++)
8635 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8636 VectorScale(center, 0.25f, center);
8637 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8638 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8639 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8640 for (i = 0;i < 4;i++)
8642 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8643 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8646 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8647 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8648 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);
8650 case Q3DEFORM_AUTOSPRITE2:
8651 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8652 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8653 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8654 VectorNormalize(newforward);
8655 VectorNormalize(newright);
8656 VectorNormalize(newup);
8657 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8658 // rsurface.batchvertex3f_vertexbuffer = NULL;
8659 // rsurface.batchvertex3f_bufferoffset = 0;
8661 const float *v1, *v2;
8671 memset(shortest, 0, sizeof(shortest));
8672 // a single autosprite surface can contain multiple sprites...
8673 for (j = 0;j < batchnumvertices - 3;j += 4)
8675 VectorClear(center);
8676 for (i = 0;i < 4;i++)
8677 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8678 VectorScale(center, 0.25f, center);
8679 // find the two shortest edges, then use them to define the
8680 // axis vectors for rotating around the central axis
8681 for (i = 0;i < 6;i++)
8683 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8684 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8685 l = VectorDistance2(v1, v2);
8686 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8688 l += (1.0f / 1024.0f);
8689 if (shortest[0].length2 > l || i == 0)
8691 shortest[1] = shortest[0];
8692 shortest[0].length2 = l;
8693 shortest[0].v1 = v1;
8694 shortest[0].v2 = v2;
8696 else if (shortest[1].length2 > l || i == 1)
8698 shortest[1].length2 = l;
8699 shortest[1].v1 = v1;
8700 shortest[1].v2 = v2;
8703 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8704 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8705 // this calculates the right vector from the shortest edge
8706 // and the up vector from the edge midpoints
8707 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8708 VectorNormalize(right);
8709 VectorSubtract(end, start, up);
8710 VectorNormalize(up);
8711 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8712 VectorSubtract(rsurface.localvieworigin, center, forward);
8713 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8714 VectorNegate(forward, forward);
8715 VectorReflect(forward, 0, up, forward);
8716 VectorNormalize(forward);
8717 CrossProduct(up, forward, newright);
8718 VectorNormalize(newright);
8719 // rotate the quad around the up axis vector, this is made
8720 // especially easy by the fact we know the quad is flat,
8721 // so we only have to subtract the center position and
8722 // measure distance along the right vector, and then
8723 // multiply that by the newright vector and add back the
8725 // we also need to subtract the old position to undo the
8726 // displacement from the center, which we do with a
8727 // DotProduct, the subtraction/addition of center is also
8728 // optimized into DotProducts here
8729 l = DotProduct(right, center);
8730 for (i = 0;i < 4;i++)
8732 v1 = rsurface.batchvertex3f + 3*(j+i);
8733 f = DotProduct(right, v1) - l;
8734 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8738 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8740 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8741 // rsurface.batchnormal3f_vertexbuffer = NULL;
8742 // rsurface.batchnormal3f_bufferoffset = 0;
8743 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8745 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8747 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8748 // rsurface.batchsvector3f_vertexbuffer = NULL;
8749 // rsurface.batchsvector3f_bufferoffset = 0;
8750 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8751 // rsurface.batchtvector3f_vertexbuffer = NULL;
8752 // rsurface.batchtvector3f_bufferoffset = 0;
8753 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);
8756 case Q3DEFORM_NORMAL:
8757 // deform the normals to make reflections wavey
8758 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8759 rsurface.batchnormal3f_vertexbuffer = NULL;
8760 rsurface.batchnormal3f_bufferoffset = 0;
8761 for (j = 0;j < batchnumvertices;j++)
8764 float *normal = rsurface.batchnormal3f + 3*j;
8765 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8766 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8767 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]);
8768 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]);
8769 VectorNormalize(normal);
8771 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8773 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8774 // rsurface.batchsvector3f_vertexbuffer = NULL;
8775 // rsurface.batchsvector3f_bufferoffset = 0;
8776 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8777 // rsurface.batchtvector3f_vertexbuffer = NULL;
8778 // rsurface.batchtvector3f_bufferoffset = 0;
8779 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);
8783 // deform vertex array to make wavey water and flags and such
8784 waveparms[0] = deform->waveparms[0];
8785 waveparms[1] = deform->waveparms[1];
8786 waveparms[2] = deform->waveparms[2];
8787 waveparms[3] = deform->waveparms[3];
8788 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8789 break; // if wavefunc is a nop, don't make a dynamic vertex array
8790 // this is how a divisor of vertex influence on deformation
8791 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8792 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8793 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8794 // rsurface.batchvertex3f_vertexbuffer = NULL;
8795 // rsurface.batchvertex3f_bufferoffset = 0;
8796 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8797 // rsurface.batchnormal3f_vertexbuffer = NULL;
8798 // rsurface.batchnormal3f_bufferoffset = 0;
8799 for (j = 0;j < batchnumvertices;j++)
8801 // if the wavefunc depends on time, evaluate it per-vertex
8804 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8805 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8807 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8809 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8810 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8811 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8813 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8814 // rsurface.batchsvector3f_vertexbuffer = NULL;
8815 // rsurface.batchsvector3f_bufferoffset = 0;
8816 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8817 // rsurface.batchtvector3f_vertexbuffer = NULL;
8818 // rsurface.batchtvector3f_bufferoffset = 0;
8819 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);
8822 case Q3DEFORM_BULGE:
8823 // deform vertex array to make the surface have moving bulges
8824 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8825 // rsurface.batchvertex3f_vertexbuffer = NULL;
8826 // rsurface.batchvertex3f_bufferoffset = 0;
8827 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8828 // rsurface.batchnormal3f_vertexbuffer = NULL;
8829 // rsurface.batchnormal3f_bufferoffset = 0;
8830 for (j = 0;j < batchnumvertices;j++)
8832 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8833 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8835 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8836 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8837 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8839 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8840 // rsurface.batchsvector3f_vertexbuffer = NULL;
8841 // rsurface.batchsvector3f_bufferoffset = 0;
8842 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8843 // rsurface.batchtvector3f_vertexbuffer = NULL;
8844 // rsurface.batchtvector3f_bufferoffset = 0;
8845 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);
8849 // deform vertex array
8850 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8851 break; // if wavefunc is a nop, don't make a dynamic vertex array
8852 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8853 VectorScale(deform->parms, scale, waveparms);
8854 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8855 // rsurface.batchvertex3f_vertexbuffer = NULL;
8856 // rsurface.batchvertex3f_bufferoffset = 0;
8857 for (j = 0;j < batchnumvertices;j++)
8858 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8863 // generate texcoords based on the chosen texcoord source
8864 switch(rsurface.texture->tcgen.tcgen)
8867 case Q3TCGEN_TEXTURE:
8869 case Q3TCGEN_LIGHTMAP:
8870 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8871 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8872 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8873 if (rsurface.batchtexcoordlightmap2f)
8874 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8876 case Q3TCGEN_VECTOR:
8877 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8878 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8879 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8880 for (j = 0;j < batchnumvertices;j++)
8882 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8883 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8886 case Q3TCGEN_ENVIRONMENT:
8887 // make environment reflections using a spheremap
8888 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8889 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8890 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8891 for (j = 0;j < batchnumvertices;j++)
8893 // identical to Q3A's method, but executed in worldspace so
8894 // carried models can be shiny too
8896 float viewer[3], d, reflected[3], worldreflected[3];
8898 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8899 // VectorNormalize(viewer);
8901 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8903 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8904 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8905 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8906 // note: this is proportinal to viewer, so we can normalize later
8908 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8909 VectorNormalize(worldreflected);
8911 // note: this sphere map only uses world x and z!
8912 // so positive and negative y will LOOK THE SAME.
8913 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8914 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8918 // the only tcmod that needs software vertex processing is turbulent, so
8919 // check for it here and apply the changes if needed
8920 // and we only support that as the first one
8921 // (handling a mixture of turbulent and other tcmods would be problematic
8922 // without punting it entirely to a software path)
8923 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8925 amplitude = rsurface.texture->tcmods[0].parms[1];
8926 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8927 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8928 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8929 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8930 for (j = 0;j < batchnumvertices;j++)
8932 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);
8933 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8937 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8939 // convert the modified arrays to vertex structs
8940 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8941 // rsurface.batchvertexmeshbuffer = NULL;
8942 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8943 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8944 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8945 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8946 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8947 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
8948 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
8950 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8952 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
8953 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
8956 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
8957 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8958 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
8959 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
8960 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8961 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
8962 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
8963 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8964 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
8968 void RSurf_DrawBatch(void)
8970 // sometimes a zero triangle surface (usually a degenerate patch) makes it
8971 // through the pipeline, killing it earlier in the pipeline would have
8972 // per-surface overhead rather than per-batch overhead, so it's best to
8973 // reject it here, before it hits glDraw.
8974 if (rsurface.batchnumtriangles == 0)
8977 // batch debugging code
8978 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
8984 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
8985 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
8988 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
8990 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
8992 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
8993 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);
9000 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);
9003 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9005 // pick the closest matching water plane
9006 int planeindex, vertexindex, bestplaneindex = -1;
9010 r_waterstate_waterplane_t *p;
9011 qboolean prepared = false;
9013 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9015 if(p->camera_entity != rsurface.texture->camera_entity)
9020 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9022 if(rsurface.batchnumvertices == 0)
9025 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9027 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9028 d += fabs(PlaneDiff(vert, &p->plane));
9030 if (bestd > d || bestplaneindex < 0)
9033 bestplaneindex = planeindex;
9036 return bestplaneindex;
9037 // NOTE: this MAY return a totally unrelated water plane; we can ignore
9038 // this situation though, as it might be better to render single larger
9039 // batches with useless stuff (backface culled for example) than to
9040 // render multiple smaller batches
9043 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9046 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9047 rsurface.passcolor4f_vertexbuffer = 0;
9048 rsurface.passcolor4f_bufferoffset = 0;
9049 for (i = 0;i < rsurface.batchnumvertices;i++)
9050 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9053 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9060 if (rsurface.passcolor4f)
9062 // generate color arrays
9063 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9064 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9065 rsurface.passcolor4f_vertexbuffer = 0;
9066 rsurface.passcolor4f_bufferoffset = 0;
9067 for (i = 0, 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)
9069 f = RSurf_FogVertex(v);
9078 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9079 rsurface.passcolor4f_vertexbuffer = 0;
9080 rsurface.passcolor4f_bufferoffset = 0;
9081 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9083 f = RSurf_FogVertex(v);
9092 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9099 if (!rsurface.passcolor4f)
9101 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9102 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9103 rsurface.passcolor4f_vertexbuffer = 0;
9104 rsurface.passcolor4f_bufferoffset = 0;
9105 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)
9107 f = RSurf_FogVertex(v);
9108 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9109 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9110 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9115 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9120 if (!rsurface.passcolor4f)
9122 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9123 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9124 rsurface.passcolor4f_vertexbuffer = 0;
9125 rsurface.passcolor4f_bufferoffset = 0;
9126 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9135 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
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)
9148 c2[0] = c[0] + r_refdef.scene.ambient;
9149 c2[1] = c[1] + r_refdef.scene.ambient;
9150 c2[2] = c[2] + r_refdef.scene.ambient;
9155 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9158 rsurface.passcolor4f = NULL;
9159 rsurface.passcolor4f_vertexbuffer = 0;
9160 rsurface.passcolor4f_bufferoffset = 0;
9161 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9162 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9163 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9164 GL_Color(r, g, b, a);
9165 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9169 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9171 // TODO: optimize applyfog && applycolor case
9172 // just apply fog if necessary, and tint the fog color array if necessary
9173 rsurface.passcolor4f = NULL;
9174 rsurface.passcolor4f_vertexbuffer = 0;
9175 rsurface.passcolor4f_bufferoffset = 0;
9176 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9177 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9178 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9179 GL_Color(r, g, b, a);
9183 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9186 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9187 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9188 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9189 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9190 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9191 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9192 GL_Color(r, g, b, a);
9196 static void RSurf_DrawBatch_GL11_ClampColor(void)
9201 if (!rsurface.passcolor4f)
9203 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9205 c2[0] = bound(0.0f, c1[0], 1.0f);
9206 c2[1] = bound(0.0f, c1[1], 1.0f);
9207 c2[2] = bound(0.0f, c1[2], 1.0f);
9208 c2[3] = bound(0.0f, c1[3], 1.0f);
9212 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9222 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9223 rsurface.passcolor4f_vertexbuffer = 0;
9224 rsurface.passcolor4f_bufferoffset = 0;
9225 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)
9227 f = -DotProduct(r_refdef.view.forward, n);
9229 f = f * 0.85 + 0.15; // work around so stuff won't get black
9230 f *= r_refdef.lightmapintensity;
9231 Vector4Set(c, f, f, f, 1);
9235 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9237 RSurf_DrawBatch_GL11_ApplyFakeLight();
9238 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9239 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9240 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9241 GL_Color(r, g, b, a);
9245 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9253 vec3_t ambientcolor;
9254 vec3_t diffusecolor;
9258 VectorCopy(rsurface.modellight_lightdir, lightdir);
9259 f = 0.5f * r_refdef.lightmapintensity;
9260 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9261 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9262 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9263 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9264 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9265 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9267 if (VectorLength2(diffusecolor) > 0)
9269 // q3-style directional shading
9270 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9271 rsurface.passcolor4f_vertexbuffer = 0;
9272 rsurface.passcolor4f_bufferoffset = 0;
9273 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)
9275 if ((f = DotProduct(n, lightdir)) > 0)
9276 VectorMA(ambientcolor, f, diffusecolor, c);
9278 VectorCopy(ambientcolor, c);
9285 *applycolor = false;
9289 *r = ambientcolor[0];
9290 *g = ambientcolor[1];
9291 *b = ambientcolor[2];
9292 rsurface.passcolor4f = NULL;
9293 rsurface.passcolor4f_vertexbuffer = 0;
9294 rsurface.passcolor4f_bufferoffset = 0;
9298 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9300 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9301 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9302 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9303 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9304 GL_Color(r, g, b, a);
9308 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9316 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9317 rsurface.passcolor4f_vertexbuffer = 0;
9318 rsurface.passcolor4f_bufferoffset = 0;
9320 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9322 f = 1 - RSurf_FogVertex(v);
9330 void RSurf_SetupDepthAndCulling(void)
9332 // submodels are biased to avoid z-fighting with world surfaces that they
9333 // may be exactly overlapping (avoids z-fighting artifacts on certain
9334 // doors and things in Quake maps)
9335 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9336 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9337 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9338 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9341 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9343 // transparent sky would be ridiculous
9344 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9346 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9347 skyrenderlater = true;
9348 RSurf_SetupDepthAndCulling();
9350 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9351 // skymasking on them, and Quake3 never did sky masking (unlike
9352 // software Quake and software Quake2), so disable the sky masking
9353 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9354 // and skymasking also looks very bad when noclipping outside the
9355 // level, so don't use it then either.
9356 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9358 R_Mesh_ResetTextureState();
9359 if (skyrendermasked)
9361 R_SetupShader_DepthOrShadow();
9362 // depth-only (masking)
9363 GL_ColorMask(0,0,0,0);
9364 // just to make sure that braindead drivers don't draw
9365 // anything despite that colormask...
9366 GL_BlendFunc(GL_ZERO, GL_ONE);
9367 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9368 if (rsurface.batchvertex3fbuffer)
9369 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9371 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9375 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9377 GL_BlendFunc(GL_ONE, GL_ZERO);
9378 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9379 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9380 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9383 if (skyrendermasked)
9384 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9386 R_Mesh_ResetTextureState();
9387 GL_Color(1, 1, 1, 1);
9390 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9391 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9392 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9394 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9398 // render screenspace normalmap to texture
9400 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9405 // bind lightmap texture
9407 // water/refraction/reflection/camera surfaces have to be handled specially
9408 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9410 int start, end, startplaneindex;
9411 for (start = 0;start < texturenumsurfaces;start = end)
9413 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9414 if(startplaneindex < 0)
9416 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9417 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9421 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9423 // now that we have a batch using the same planeindex, render it
9424 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9426 // render water or distortion background
9428 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));
9430 // blend surface on top
9431 GL_DepthMask(false);
9432 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9435 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9437 // render surface with reflection texture as input
9438 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9439 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));
9446 // render surface batch normally
9447 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9448 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9452 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9454 // OpenGL 1.3 path - anything not completely ancient
9455 qboolean applycolor;
9458 const texturelayer_t *layer;
9459 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);
9460 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9462 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9465 int layertexrgbscale;
9466 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9468 if (layerindex == 0)
9472 GL_AlphaTest(false);
9473 GL_DepthFunc(GL_EQUAL);
9476 GL_DepthMask(layer->depthmask && writedepth);
9477 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9478 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9480 layertexrgbscale = 4;
9481 VectorScale(layer->color, 0.25f, layercolor);
9483 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9485 layertexrgbscale = 2;
9486 VectorScale(layer->color, 0.5f, layercolor);
9490 layertexrgbscale = 1;
9491 VectorScale(layer->color, 1.0f, layercolor);
9493 layercolor[3] = layer->color[3];
9494 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9495 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9496 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9497 switch (layer->type)
9499 case TEXTURELAYERTYPE_LITTEXTURE:
9500 // single-pass lightmapped texture with 2x rgbscale
9501 R_Mesh_TexBind(0, r_texture_white);
9502 R_Mesh_TexMatrix(0, NULL);
9503 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9504 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9505 R_Mesh_TexBind(1, layer->texture);
9506 R_Mesh_TexMatrix(1, &layer->texmatrix);
9507 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9508 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9509 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9510 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9511 else if (FAKELIGHT_ENABLED)
9512 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9513 else if (rsurface.uselightmaptexture)
9514 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9516 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9518 case TEXTURELAYERTYPE_TEXTURE:
9519 // singletexture unlit texture with transparency support
9520 R_Mesh_TexBind(0, layer->texture);
9521 R_Mesh_TexMatrix(0, &layer->texmatrix);
9522 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9523 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9524 R_Mesh_TexBind(1, 0);
9525 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9526 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9528 case TEXTURELAYERTYPE_FOG:
9529 // singletexture fogging
9532 R_Mesh_TexBind(0, layer->texture);
9533 R_Mesh_TexMatrix(0, &layer->texmatrix);
9534 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9535 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9539 R_Mesh_TexBind(0, 0);
9540 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9542 R_Mesh_TexBind(1, 0);
9543 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9544 // generate a color array for the fog pass
9545 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9546 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9550 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9553 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9555 GL_DepthFunc(GL_LEQUAL);
9556 GL_AlphaTest(false);
9560 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9562 // OpenGL 1.1 - crusty old voodoo path
9565 const texturelayer_t *layer;
9566 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);
9567 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9569 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9571 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9573 if (layerindex == 0)
9577 GL_AlphaTest(false);
9578 GL_DepthFunc(GL_EQUAL);
9581 GL_DepthMask(layer->depthmask && writedepth);
9582 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9583 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9584 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9585 switch (layer->type)
9587 case TEXTURELAYERTYPE_LITTEXTURE:
9588 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9590 // two-pass lit texture with 2x rgbscale
9591 // first the lightmap pass
9592 R_Mesh_TexBind(0, r_texture_white);
9593 R_Mesh_TexMatrix(0, NULL);
9594 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9595 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9596 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9597 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9598 else if (FAKELIGHT_ENABLED)
9599 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9600 else if (rsurface.uselightmaptexture)
9601 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9603 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9604 // then apply the texture to it
9605 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9606 R_Mesh_TexBind(0, layer->texture);
9607 R_Mesh_TexMatrix(0, &layer->texmatrix);
9608 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9609 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9610 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);
9614 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9615 R_Mesh_TexBind(0, layer->texture);
9616 R_Mesh_TexMatrix(0, &layer->texmatrix);
9617 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9618 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9619 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9620 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);
9622 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);
9625 case TEXTURELAYERTYPE_TEXTURE:
9626 // singletexture unlit texture with transparency support
9627 R_Mesh_TexBind(0, layer->texture);
9628 R_Mesh_TexMatrix(0, &layer->texmatrix);
9629 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9630 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9631 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);
9633 case TEXTURELAYERTYPE_FOG:
9634 // singletexture fogging
9637 R_Mesh_TexBind(0, layer->texture);
9638 R_Mesh_TexMatrix(0, &layer->texmatrix);
9639 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9640 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9644 R_Mesh_TexBind(0, 0);
9645 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9647 // generate a color array for the fog pass
9648 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9649 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9653 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9656 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9658 GL_DepthFunc(GL_LEQUAL);
9659 GL_AlphaTest(false);
9663 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9667 r_vertexgeneric_t *batchvertex;
9670 // R_Mesh_ResetTextureState();
9671 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9673 if(rsurface.texture && rsurface.texture->currentskinframe)
9675 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9676 c[3] *= rsurface.texture->currentalpha;
9686 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9688 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9689 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9690 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9693 // brighten it up (as texture value 127 means "unlit")
9694 c[0] *= 2 * r_refdef.view.colorscale;
9695 c[1] *= 2 * r_refdef.view.colorscale;
9696 c[2] *= 2 * r_refdef.view.colorscale;
9698 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9699 c[3] *= r_wateralpha.value;
9701 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9703 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9704 GL_DepthMask(false);
9706 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9708 GL_BlendFunc(GL_ONE, GL_ONE);
9709 GL_DepthMask(false);
9711 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9713 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9714 GL_DepthMask(false);
9716 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9718 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9719 GL_DepthMask(false);
9723 GL_BlendFunc(GL_ONE, GL_ZERO);
9724 GL_DepthMask(writedepth);
9727 if (r_showsurfaces.integer == 3)
9729 rsurface.passcolor4f = NULL;
9731 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9733 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9735 rsurface.passcolor4f = NULL;
9736 rsurface.passcolor4f_vertexbuffer = 0;
9737 rsurface.passcolor4f_bufferoffset = 0;
9739 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9741 qboolean applycolor = true;
9744 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9746 r_refdef.lightmapintensity = 1;
9747 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9748 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9750 else if (FAKELIGHT_ENABLED)
9752 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9754 r_refdef.lightmapintensity = r_fakelight_intensity.value;
9755 RSurf_DrawBatch_GL11_ApplyFakeLight();
9756 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9760 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9762 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9763 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9764 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9767 if(!rsurface.passcolor4f)
9768 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9770 RSurf_DrawBatch_GL11_ApplyAmbient();
9771 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9772 if(r_refdef.fogenabled)
9773 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9774 RSurf_DrawBatch_GL11_ClampColor();
9776 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9777 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9780 else if (!r_refdef.view.showdebug)
9782 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9783 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9784 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9786 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9787 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9789 R_Mesh_PrepareVertices_Generic_Unlock();
9792 else if (r_showsurfaces.integer == 4)
9794 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9795 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9796 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9798 unsigned char c = (vi << 3) * (1.0f / 256.0f);
9799 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9800 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9802 R_Mesh_PrepareVertices_Generic_Unlock();
9805 else if (r_showsurfaces.integer == 2)
9808 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9809 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9810 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9812 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9813 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9814 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9815 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9816 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9817 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9818 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9820 R_Mesh_PrepareVertices_Generic_Unlock();
9821 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9825 int texturesurfaceindex;
9827 const msurface_t *surface;
9828 float surfacecolor4f[4];
9829 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9830 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9832 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9834 surface = texturesurfacelist[texturesurfaceindex];
9835 k = (int)(((size_t)surface) / sizeof(msurface_t));
9836 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9837 for (j = 0;j < surface->num_vertices;j++)
9839 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9840 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9844 R_Mesh_PrepareVertices_Generic_Unlock();
9849 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9852 RSurf_SetupDepthAndCulling();
9853 if (r_showsurfaces.integer)
9855 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9858 switch (vid.renderpath)
9860 case RENDERPATH_GL20:
9861 case RENDERPATH_D3D9:
9862 case RENDERPATH_D3D10:
9863 case RENDERPATH_D3D11:
9864 case RENDERPATH_SOFT:
9865 case RENDERPATH_GLES2:
9866 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9868 case RENDERPATH_GL13:
9869 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9871 case RENDERPATH_GL11:
9872 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9878 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9881 RSurf_SetupDepthAndCulling();
9882 if (r_showsurfaces.integer)
9884 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9887 switch (vid.renderpath)
9889 case RENDERPATH_GL20:
9890 case RENDERPATH_D3D9:
9891 case RENDERPATH_D3D10:
9892 case RENDERPATH_D3D11:
9893 case RENDERPATH_SOFT:
9894 case RENDERPATH_GLES2:
9895 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9897 case RENDERPATH_GL13:
9898 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9900 case RENDERPATH_GL11:
9901 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9907 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9910 int texturenumsurfaces, endsurface;
9912 const msurface_t *surface;
9913 #define MAXBATCH_TRANSPARENTSURFACES 256
9914 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9916 // if the model is static it doesn't matter what value we give for
9917 // wantnormals and wanttangents, so this logic uses only rules applicable
9918 // to a model, knowing that they are meaningless otherwise
9919 if (ent == r_refdef.scene.worldentity)
9920 RSurf_ActiveWorldEntity();
9921 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9922 RSurf_ActiveModelEntity(ent, false, false, false);
9925 switch (vid.renderpath)
9927 case RENDERPATH_GL20:
9928 case RENDERPATH_D3D9:
9929 case RENDERPATH_D3D10:
9930 case RENDERPATH_D3D11:
9931 case RENDERPATH_SOFT:
9932 case RENDERPATH_GLES2:
9933 RSurf_ActiveModelEntity(ent, true, true, false);
9935 case RENDERPATH_GL13:
9936 case RENDERPATH_GL11:
9937 RSurf_ActiveModelEntity(ent, true, false, false);
9942 if (r_transparentdepthmasking.integer)
9944 qboolean setup = false;
9945 for (i = 0;i < numsurfaces;i = j)
9948 surface = rsurface.modelsurfaces + surfacelist[i];
9949 texture = surface->texture;
9950 rsurface.texture = R_GetCurrentTexture(texture);
9951 rsurface.lightmaptexture = NULL;
9952 rsurface.deluxemaptexture = NULL;
9953 rsurface.uselightmaptexture = false;
9954 // scan ahead until we find a different texture
9955 endsurface = min(i + 1024, numsurfaces);
9956 texturenumsurfaces = 0;
9957 texturesurfacelist[texturenumsurfaces++] = surface;
9958 for (;j < endsurface;j++)
9960 surface = rsurface.modelsurfaces + surfacelist[j];
9961 if (texture != surface->texture)
9963 texturesurfacelist[texturenumsurfaces++] = surface;
9965 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9967 // render the range of surfaces as depth
9971 GL_ColorMask(0,0,0,0);
9974 GL_BlendFunc(GL_ONE, GL_ZERO);
9976 // R_Mesh_ResetTextureState();
9977 R_SetupShader_DepthOrShadow();
9979 RSurf_SetupDepthAndCulling();
9980 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9981 if (rsurface.batchvertex3fbuffer)
9982 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9984 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9988 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9991 for (i = 0;i < numsurfaces;i = j)
9994 surface = rsurface.modelsurfaces + surfacelist[i];
9995 texture = surface->texture;
9996 rsurface.texture = R_GetCurrentTexture(texture);
9997 // scan ahead until we find a different texture
9998 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
9999 texturenumsurfaces = 0;
10000 texturesurfacelist[texturenumsurfaces++] = surface;
10001 if(FAKELIGHT_ENABLED)
10003 rsurface.lightmaptexture = NULL;
10004 rsurface.deluxemaptexture = NULL;
10005 rsurface.uselightmaptexture = false;
10006 for (;j < endsurface;j++)
10008 surface = rsurface.modelsurfaces + surfacelist[j];
10009 if (texture != surface->texture)
10011 texturesurfacelist[texturenumsurfaces++] = surface;
10016 rsurface.lightmaptexture = surface->lightmaptexture;
10017 rsurface.deluxemaptexture = surface->deluxemaptexture;
10018 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10019 for (;j < endsurface;j++)
10021 surface = rsurface.modelsurfaces + surfacelist[j];
10022 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10024 texturesurfacelist[texturenumsurfaces++] = surface;
10027 // render the range of surfaces
10028 if (ent == r_refdef.scene.worldentity)
10029 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10031 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10033 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10036 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10038 // transparent surfaces get pushed off into the transparent queue
10039 int surfacelistindex;
10040 const msurface_t *surface;
10041 vec3_t tempcenter, center;
10042 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10044 surface = texturesurfacelist[surfacelistindex];
10045 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10046 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10047 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10048 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10049 if (queueentity->transparent_offset) // transparent offset
10051 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10052 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10053 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10055 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10059 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10061 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10063 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10065 RSurf_SetupDepthAndCulling();
10066 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10067 if (rsurface.batchvertex3fbuffer)
10068 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10070 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10074 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10076 const entity_render_t *queueentity = r_refdef.scene.worldentity;
10079 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10082 if (!rsurface.texture->currentnumlayers)
10084 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10085 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10087 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10089 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10090 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10091 else if (!rsurface.texture->currentnumlayers)
10093 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10095 // in the deferred case, transparent surfaces were queued during prepass
10096 if (!r_shadow_usingdeferredprepass)
10097 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10101 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10102 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10107 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10110 texture_t *texture;
10111 R_FrameData_SetMark();
10112 // break the surface list down into batches by texture and use of lightmapping
10113 for (i = 0;i < numsurfaces;i = j)
10116 // texture is the base texture pointer, rsurface.texture is the
10117 // current frame/skin the texture is directing us to use (for example
10118 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10119 // use skin 1 instead)
10120 texture = surfacelist[i]->texture;
10121 rsurface.texture = R_GetCurrentTexture(texture);
10122 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10124 // if this texture is not the kind we want, skip ahead to the next one
10125 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10129 if(FAKELIGHT_ENABLED || depthonly || prepass)
10131 rsurface.lightmaptexture = NULL;
10132 rsurface.deluxemaptexture = NULL;
10133 rsurface.uselightmaptexture = false;
10134 // simply scan ahead until we find a different texture or lightmap state
10135 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10140 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10141 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10142 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10143 // simply scan ahead until we find a different texture or lightmap state
10144 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10147 // render the range of surfaces
10148 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10150 R_FrameData_ReturnToMark();
10153 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10157 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10160 if (!rsurface.texture->currentnumlayers)
10162 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10163 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10165 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10167 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10168 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10169 else if (!rsurface.texture->currentnumlayers)
10171 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10173 // in the deferred case, transparent surfaces were queued during prepass
10174 if (!r_shadow_usingdeferredprepass)
10175 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10179 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10180 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10185 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10188 texture_t *texture;
10189 R_FrameData_SetMark();
10190 // break the surface list down into batches by texture and use of lightmapping
10191 for (i = 0;i < numsurfaces;i = j)
10194 // texture is the base texture pointer, rsurface.texture is the
10195 // current frame/skin the texture is directing us to use (for example
10196 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10197 // use skin 1 instead)
10198 texture = surfacelist[i]->texture;
10199 rsurface.texture = R_GetCurrentTexture(texture);
10200 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10202 // if this texture is not the kind we want, skip ahead to the next one
10203 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10207 if(FAKELIGHT_ENABLED || depthonly || prepass)
10209 rsurface.lightmaptexture = NULL;
10210 rsurface.deluxemaptexture = NULL;
10211 rsurface.uselightmaptexture = false;
10212 // simply scan ahead until we find a different texture or lightmap state
10213 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10218 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10219 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10220 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10221 // simply scan ahead until we find a different texture or lightmap state
10222 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10225 // render the range of surfaces
10226 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10228 R_FrameData_ReturnToMark();
10231 float locboxvertex3f[6*4*3] =
10233 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10234 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10235 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10236 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10237 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10238 1,0,0, 0,0,0, 0,1,0, 1,1,0
10241 unsigned short locboxelements[6*2*3] =
10246 12,13,14, 12,14,15,
10247 16,17,18, 16,18,19,
10251 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10254 cl_locnode_t *loc = (cl_locnode_t *)ent;
10256 float vertex3f[6*4*3];
10258 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10259 GL_DepthMask(false);
10260 GL_DepthRange(0, 1);
10261 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10262 GL_DepthTest(true);
10263 GL_CullFace(GL_NONE);
10264 R_EntityMatrix(&identitymatrix);
10266 // R_Mesh_ResetTextureState();
10268 i = surfacelist[0];
10269 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10270 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10271 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10272 surfacelist[0] < 0 ? 0.5f : 0.125f);
10274 if (VectorCompare(loc->mins, loc->maxs))
10276 VectorSet(size, 2, 2, 2);
10277 VectorMA(loc->mins, -0.5f, size, mins);
10281 VectorCopy(loc->mins, mins);
10282 VectorSubtract(loc->maxs, loc->mins, size);
10285 for (i = 0;i < 6*4*3;)
10286 for (j = 0;j < 3;j++, i++)
10287 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10289 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10290 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10291 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10294 void R_DrawLocs(void)
10297 cl_locnode_t *loc, *nearestloc;
10299 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10300 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10302 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10303 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10307 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10309 if (decalsystem->decals)
10310 Mem_Free(decalsystem->decals);
10311 memset(decalsystem, 0, sizeof(*decalsystem));
10314 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)
10317 tridecal_t *decals;
10320 // expand or initialize the system
10321 if (decalsystem->maxdecals <= decalsystem->numdecals)
10323 decalsystem_t old = *decalsystem;
10324 qboolean useshortelements;
10325 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10326 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10327 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)));
10328 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10329 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10330 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10331 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10332 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10333 if (decalsystem->numdecals)
10334 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10336 Mem_Free(old.decals);
10337 for (i = 0;i < decalsystem->maxdecals*3;i++)
10338 decalsystem->element3i[i] = i;
10339 if (useshortelements)
10340 for (i = 0;i < decalsystem->maxdecals*3;i++)
10341 decalsystem->element3s[i] = i;
10344 // grab a decal and search for another free slot for the next one
10345 decals = decalsystem->decals;
10346 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10347 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10349 decalsystem->freedecal = i;
10350 if (decalsystem->numdecals <= i)
10351 decalsystem->numdecals = i + 1;
10353 // initialize the decal
10355 decal->triangleindex = triangleindex;
10356 decal->surfaceindex = surfaceindex;
10357 decal->decalsequence = decalsequence;
10358 decal->color4f[0][0] = c0[0];
10359 decal->color4f[0][1] = c0[1];
10360 decal->color4f[0][2] = c0[2];
10361 decal->color4f[0][3] = 1;
10362 decal->color4f[1][0] = c1[0];
10363 decal->color4f[1][1] = c1[1];
10364 decal->color4f[1][2] = c1[2];
10365 decal->color4f[1][3] = 1;
10366 decal->color4f[2][0] = c2[0];
10367 decal->color4f[2][1] = c2[1];
10368 decal->color4f[2][2] = c2[2];
10369 decal->color4f[2][3] = 1;
10370 decal->vertex3f[0][0] = v0[0];
10371 decal->vertex3f[0][1] = v0[1];
10372 decal->vertex3f[0][2] = v0[2];
10373 decal->vertex3f[1][0] = v1[0];
10374 decal->vertex3f[1][1] = v1[1];
10375 decal->vertex3f[1][2] = v1[2];
10376 decal->vertex3f[2][0] = v2[0];
10377 decal->vertex3f[2][1] = v2[1];
10378 decal->vertex3f[2][2] = v2[2];
10379 decal->texcoord2f[0][0] = t0[0];
10380 decal->texcoord2f[0][1] = t0[1];
10381 decal->texcoord2f[1][0] = t1[0];
10382 decal->texcoord2f[1][1] = t1[1];
10383 decal->texcoord2f[2][0] = t2[0];
10384 decal->texcoord2f[2][1] = t2[1];
10385 TriangleNormal(v0, v1, v2, decal->plane);
10386 VectorNormalize(decal->plane);
10387 decal->plane[3] = DotProduct(v0, decal->plane);
10390 extern cvar_t cl_decals_bias;
10391 extern cvar_t cl_decals_models;
10392 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10393 // baseparms, parms, temps
10394 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)
10399 const float *vertex3f;
10400 const float *normal3f;
10402 float points[2][9][3];
10409 e = rsurface.modelelement3i + 3*triangleindex;
10411 vertex3f = rsurface.modelvertex3f;
10412 normal3f = rsurface.modelnormal3f;
10416 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10418 index = 3*e[cornerindex];
10419 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10424 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10426 index = 3*e[cornerindex];
10427 VectorCopy(vertex3f + index, v[cornerindex]);
10432 //TriangleNormal(v[0], v[1], v[2], normal);
10433 //if (DotProduct(normal, localnormal) < 0.0f)
10435 // clip by each of the box planes formed from the projection matrix
10436 // if anything survives, we emit the decal
10437 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]);
10440 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]);
10443 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]);
10446 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]);
10449 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]);
10452 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]);
10455 // some part of the triangle survived, so we have to accept it...
10458 // dynamic always uses the original triangle
10460 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10462 index = 3*e[cornerindex];
10463 VectorCopy(vertex3f + index, v[cornerindex]);
10466 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10468 // convert vertex positions to texcoords
10469 Matrix4x4_Transform(projection, v[cornerindex], temp);
10470 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10471 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10472 // calculate distance fade from the projection origin
10473 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10474 f = bound(0.0f, f, 1.0f);
10475 c[cornerindex][0] = r * f;
10476 c[cornerindex][1] = g * f;
10477 c[cornerindex][2] = b * f;
10478 c[cornerindex][3] = 1.0f;
10479 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10482 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);
10484 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10485 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);
10487 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)
10489 matrix4x4_t projection;
10490 decalsystem_t *decalsystem;
10493 const msurface_t *surface;
10494 const msurface_t *surfaces;
10495 const int *surfacelist;
10496 const texture_t *texture;
10498 int numsurfacelist;
10499 int surfacelistindex;
10502 float localorigin[3];
10503 float localnormal[3];
10504 float localmins[3];
10505 float localmaxs[3];
10508 float planes[6][4];
10511 int bih_triangles_count;
10512 int bih_triangles[256];
10513 int bih_surfaces[256];
10515 decalsystem = &ent->decalsystem;
10516 model = ent->model;
10517 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10519 R_DecalSystem_Reset(&ent->decalsystem);
10523 if (!model->brush.data_leafs && !cl_decals_models.integer)
10525 if (decalsystem->model)
10526 R_DecalSystem_Reset(decalsystem);
10530 if (decalsystem->model != model)
10531 R_DecalSystem_Reset(decalsystem);
10532 decalsystem->model = model;
10534 RSurf_ActiveModelEntity(ent, true, false, false);
10536 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10537 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10538 VectorNormalize(localnormal);
10539 localsize = worldsize*rsurface.inversematrixscale;
10540 localmins[0] = localorigin[0] - localsize;
10541 localmins[1] = localorigin[1] - localsize;
10542 localmins[2] = localorigin[2] - localsize;
10543 localmaxs[0] = localorigin[0] + localsize;
10544 localmaxs[1] = localorigin[1] + localsize;
10545 localmaxs[2] = localorigin[2] + localsize;
10547 //VectorCopy(localnormal, planes[4]);
10548 //VectorVectors(planes[4], planes[2], planes[0]);
10549 AnglesFromVectors(angles, localnormal, NULL, false);
10550 AngleVectors(angles, planes[0], planes[2], planes[4]);
10551 VectorNegate(planes[0], planes[1]);
10552 VectorNegate(planes[2], planes[3]);
10553 VectorNegate(planes[4], planes[5]);
10554 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10555 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10556 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10557 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10558 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10559 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10564 matrix4x4_t forwardprojection;
10565 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10566 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10571 float projectionvector[4][3];
10572 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10573 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10574 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10575 projectionvector[0][0] = planes[0][0] * ilocalsize;
10576 projectionvector[0][1] = planes[1][0] * ilocalsize;
10577 projectionvector[0][2] = planes[2][0] * ilocalsize;
10578 projectionvector[1][0] = planes[0][1] * ilocalsize;
10579 projectionvector[1][1] = planes[1][1] * ilocalsize;
10580 projectionvector[1][2] = planes[2][1] * ilocalsize;
10581 projectionvector[2][0] = planes[0][2] * ilocalsize;
10582 projectionvector[2][1] = planes[1][2] * ilocalsize;
10583 projectionvector[2][2] = planes[2][2] * ilocalsize;
10584 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10585 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10586 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10587 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10591 dynamic = model->surfmesh.isanimated;
10592 numsurfacelist = model->nummodelsurfaces;
10593 surfacelist = model->sortedmodelsurfaces;
10594 surfaces = model->data_surfaces;
10597 bih_triangles_count = -1;
10600 if(model->render_bih.numleafs)
10601 bih = &model->render_bih;
10602 else if(model->collision_bih.numleafs)
10603 bih = &model->collision_bih;
10606 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10607 if(bih_triangles_count == 0)
10609 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10611 if(bih_triangles_count > 0)
10613 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10615 surfaceindex = bih_surfaces[triangleindex];
10616 surface = surfaces + surfaceindex;
10617 texture = surface->texture;
10618 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10620 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10622 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10627 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10629 surfaceindex = surfacelist[surfacelistindex];
10630 surface = surfaces + surfaceindex;
10631 // check cull box first because it rejects more than any other check
10632 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10634 // skip transparent surfaces
10635 texture = surface->texture;
10636 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10638 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10640 numtriangles = surface->num_triangles;
10641 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10642 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10647 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10648 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)
10650 int renderentityindex;
10651 float worldmins[3];
10652 float worldmaxs[3];
10653 entity_render_t *ent;
10655 if (!cl_decals_newsystem.integer)
10658 worldmins[0] = worldorigin[0] - worldsize;
10659 worldmins[1] = worldorigin[1] - worldsize;
10660 worldmins[2] = worldorigin[2] - worldsize;
10661 worldmaxs[0] = worldorigin[0] + worldsize;
10662 worldmaxs[1] = worldorigin[1] + worldsize;
10663 worldmaxs[2] = worldorigin[2] + worldsize;
10665 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10667 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10669 ent = r_refdef.scene.entities[renderentityindex];
10670 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10673 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10677 typedef struct r_decalsystem_splatqueue_s
10679 vec3_t worldorigin;
10680 vec3_t worldnormal;
10686 r_decalsystem_splatqueue_t;
10688 int r_decalsystem_numqueued = 0;
10689 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10691 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)
10693 r_decalsystem_splatqueue_t *queue;
10695 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10698 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10699 VectorCopy(worldorigin, queue->worldorigin);
10700 VectorCopy(worldnormal, queue->worldnormal);
10701 Vector4Set(queue->color, r, g, b, a);
10702 Vector4Set(queue->tcrange, s1, t1, s2, t2);
10703 queue->worldsize = worldsize;
10704 queue->decalsequence = cl.decalsequence++;
10707 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10710 r_decalsystem_splatqueue_t *queue;
10712 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10713 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);
10714 r_decalsystem_numqueued = 0;
10717 extern cvar_t cl_decals_max;
10718 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10721 decalsystem_t *decalsystem = &ent->decalsystem;
10728 if (!decalsystem->numdecals)
10731 if (r_showsurfaces.integer)
10734 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10736 R_DecalSystem_Reset(decalsystem);
10740 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10741 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10743 if (decalsystem->lastupdatetime)
10744 frametime = (cl.time - decalsystem->lastupdatetime);
10747 decalsystem->lastupdatetime = cl.time;
10748 decal = decalsystem->decals;
10749 numdecals = decalsystem->numdecals;
10751 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10753 if (decal->color4f[0][3])
10755 decal->lived += frametime;
10756 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10758 memset(decal, 0, sizeof(*decal));
10759 if (decalsystem->freedecal > i)
10760 decalsystem->freedecal = i;
10764 decal = decalsystem->decals;
10765 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10768 // collapse the array by shuffling the tail decals into the gaps
10771 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10772 decalsystem->freedecal++;
10773 if (decalsystem->freedecal == numdecals)
10775 decal[decalsystem->freedecal] = decal[--numdecals];
10778 decalsystem->numdecals = numdecals;
10780 if (numdecals <= 0)
10782 // if there are no decals left, reset decalsystem
10783 R_DecalSystem_Reset(decalsystem);
10787 extern skinframe_t *decalskinframe;
10788 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10791 decalsystem_t *decalsystem = &ent->decalsystem;
10800 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10803 numdecals = decalsystem->numdecals;
10807 if (r_showsurfaces.integer)
10810 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10812 R_DecalSystem_Reset(decalsystem);
10816 // if the model is static it doesn't matter what value we give for
10817 // wantnormals and wanttangents, so this logic uses only rules applicable
10818 // to a model, knowing that they are meaningless otherwise
10819 if (ent == r_refdef.scene.worldentity)
10820 RSurf_ActiveWorldEntity();
10822 RSurf_ActiveModelEntity(ent, false, false, false);
10824 decalsystem->lastupdatetime = cl.time;
10825 decal = decalsystem->decals;
10827 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10829 // update vertex positions for animated models
10830 v3f = decalsystem->vertex3f;
10831 c4f = decalsystem->color4f;
10832 t2f = decalsystem->texcoord2f;
10833 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10835 if (!decal->color4f[0][3])
10838 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10842 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
10845 // update color values for fading decals
10846 if (decal->lived >= cl_decals_time.value)
10847 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10851 c4f[ 0] = decal->color4f[0][0] * alpha;
10852 c4f[ 1] = decal->color4f[0][1] * alpha;
10853 c4f[ 2] = decal->color4f[0][2] * alpha;
10855 c4f[ 4] = decal->color4f[1][0] * alpha;
10856 c4f[ 5] = decal->color4f[1][1] * alpha;
10857 c4f[ 6] = decal->color4f[1][2] * alpha;
10859 c4f[ 8] = decal->color4f[2][0] * alpha;
10860 c4f[ 9] = decal->color4f[2][1] * alpha;
10861 c4f[10] = decal->color4f[2][2] * alpha;
10864 t2f[0] = decal->texcoord2f[0][0];
10865 t2f[1] = decal->texcoord2f[0][1];
10866 t2f[2] = decal->texcoord2f[1][0];
10867 t2f[3] = decal->texcoord2f[1][1];
10868 t2f[4] = decal->texcoord2f[2][0];
10869 t2f[5] = decal->texcoord2f[2][1];
10871 // update vertex positions for animated models
10872 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10874 e = rsurface.modelelement3i + 3*decal->triangleindex;
10875 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10876 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10877 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10881 VectorCopy(decal->vertex3f[0], v3f);
10882 VectorCopy(decal->vertex3f[1], v3f + 3);
10883 VectorCopy(decal->vertex3f[2], v3f + 6);
10886 if (r_refdef.fogenabled)
10888 alpha = RSurf_FogVertex(v3f);
10889 VectorScale(c4f, alpha, c4f);
10890 alpha = RSurf_FogVertex(v3f + 3);
10891 VectorScale(c4f + 4, alpha, c4f + 4);
10892 alpha = RSurf_FogVertex(v3f + 6);
10893 VectorScale(c4f + 8, alpha, c4f + 8);
10904 r_refdef.stats.drawndecals += numtris;
10906 // now render the decals all at once
10907 // (this assumes they all use one particle font texture!)
10908 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);
10909 // R_Mesh_ResetTextureState();
10910 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10911 GL_DepthMask(false);
10912 GL_DepthRange(0, 1);
10913 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10914 GL_DepthTest(true);
10915 GL_CullFace(GL_NONE);
10916 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10917 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10918 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10922 static void R_DrawModelDecals(void)
10926 // fade faster when there are too many decals
10927 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10928 for (i = 0;i < r_refdef.scene.numentities;i++)
10929 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10931 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10932 for (i = 0;i < r_refdef.scene.numentities;i++)
10933 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10934 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10936 R_DecalSystem_ApplySplatEntitiesQueue();
10938 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10939 for (i = 0;i < r_refdef.scene.numentities;i++)
10940 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10942 r_refdef.stats.totaldecals += numdecals;
10944 if (r_showsurfaces.integer)
10947 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10949 for (i = 0;i < r_refdef.scene.numentities;i++)
10951 if (!r_refdef.viewcache.entityvisible[i])
10953 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10954 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10958 extern cvar_t mod_collision_bih;
10959 void R_DrawDebugModel(void)
10961 entity_render_t *ent = rsurface.entity;
10962 int i, j, k, l, flagsmask;
10963 const msurface_t *surface;
10964 dp_model_t *model = ent->model;
10967 switch(vid.renderpath)
10969 case RENDERPATH_GL11:
10970 case RENDERPATH_GL13:
10971 case RENDERPATH_GL20:
10973 case RENDERPATH_D3D9:
10974 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10976 case RENDERPATH_D3D10:
10977 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10979 case RENDERPATH_D3D11:
10980 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10982 case RENDERPATH_SOFT:
10983 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10985 case RENDERPATH_GLES2:
10986 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10990 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
10992 // R_Mesh_ResetTextureState();
10993 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10994 GL_DepthRange(0, 1);
10995 GL_DepthTest(!r_showdisabledepthtest.integer);
10996 GL_DepthMask(false);
10997 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10999 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11003 qboolean cullbox = ent == r_refdef.scene.worldentity;
11004 const q3mbrush_t *brush;
11005 const bih_t *bih = &model->collision_bih;
11006 const bih_leaf_t *bihleaf;
11007 float vertex3f[3][3];
11008 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11010 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11012 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11014 switch (bihleaf->type)
11017 brush = model->brush.data_brushes + bihleaf->itemindex;
11018 if (brush->colbrushf && brush->colbrushf->numtriangles)
11020 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);
11021 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11022 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11025 case BIH_COLLISIONTRIANGLE:
11026 triangleindex = bihleaf->itemindex;
11027 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11028 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11029 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11030 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);
11031 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11032 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11034 case BIH_RENDERTRIANGLE:
11035 triangleindex = bihleaf->itemindex;
11036 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11037 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11038 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11039 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);
11040 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11041 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11047 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11049 if (r_showtris.integer || (r_shownormals.value != 0))
11051 if (r_showdisabledepthtest.integer)
11053 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11054 GL_DepthMask(false);
11058 GL_BlendFunc(GL_ONE, GL_ZERO);
11059 GL_DepthMask(true);
11061 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11063 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11065 rsurface.texture = R_GetCurrentTexture(surface->texture);
11066 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11068 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11069 if (r_showtris.value > 0)
11071 if (!rsurface.texture->currentlayers->depthmask)
11072 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11073 else if (ent == r_refdef.scene.worldentity)
11074 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11076 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11077 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11078 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
11080 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
11083 if (r_shownormals.value < 0)
11085 qglBegin(GL_LINES);
11086 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11088 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11089 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11090 qglVertex3f(v[0], v[1], v[2]);
11091 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11092 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11093 qglVertex3f(v[0], v[1], v[2]);
11098 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11100 qglBegin(GL_LINES);
11101 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11103 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11104 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11105 qglVertex3f(v[0], v[1], v[2]);
11106 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11107 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11108 qglVertex3f(v[0], v[1], v[2]);
11112 qglBegin(GL_LINES);
11113 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11115 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11116 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11117 qglVertex3f(v[0], v[1], v[2]);
11118 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11119 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11120 qglVertex3f(v[0], v[1], v[2]);
11124 qglBegin(GL_LINES);
11125 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11127 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11128 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11129 qglVertex3f(v[0], v[1], v[2]);
11130 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11131 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11132 qglVertex3f(v[0], v[1], v[2]);
11139 rsurface.texture = NULL;
11143 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11144 int r_maxsurfacelist = 0;
11145 const msurface_t **r_surfacelist = NULL;
11146 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11148 int i, j, endj, flagsmask;
11149 dp_model_t *model = r_refdef.scene.worldmodel;
11150 msurface_t *surfaces;
11151 unsigned char *update;
11152 int numsurfacelist = 0;
11156 if (r_maxsurfacelist < model->num_surfaces)
11158 r_maxsurfacelist = model->num_surfaces;
11160 Mem_Free((msurface_t**)r_surfacelist);
11161 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11164 RSurf_ActiveWorldEntity();
11166 surfaces = model->data_surfaces;
11167 update = model->brushq1.lightmapupdateflags;
11169 // update light styles on this submodel
11170 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11172 model_brush_lightstyleinfo_t *style;
11173 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11175 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11177 int *list = style->surfacelist;
11178 style->value = r_refdef.scene.lightstylevalue[style->style];
11179 for (j = 0;j < style->numsurfaces;j++)
11180 update[list[j]] = true;
11185 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11189 R_DrawDebugModel();
11190 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11194 rsurface.lightmaptexture = NULL;
11195 rsurface.deluxemaptexture = NULL;
11196 rsurface.uselightmaptexture = false;
11197 rsurface.texture = NULL;
11198 rsurface.rtlight = NULL;
11199 numsurfacelist = 0;
11200 // add visible surfaces to draw list
11201 for (i = 0;i < model->nummodelsurfaces;i++)
11203 j = model->sortedmodelsurfaces[i];
11204 if (r_refdef.viewcache.world_surfacevisible[j])
11205 r_surfacelist[numsurfacelist++] = surfaces + j;
11207 // update lightmaps if needed
11208 if (model->brushq1.firstrender)
11210 model->brushq1.firstrender = false;
11211 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11213 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11217 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11218 if (r_refdef.viewcache.world_surfacevisible[j])
11220 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11222 // don't do anything if there were no surfaces
11223 if (!numsurfacelist)
11225 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11228 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11230 // add to stats if desired
11231 if (r_speeds.integer && !skysurfaces && !depthonly)
11233 r_refdef.stats.world_surfaces += numsurfacelist;
11234 for (j = 0;j < numsurfacelist;j++)
11235 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11238 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11241 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11243 int i, j, endj, flagsmask;
11244 dp_model_t *model = ent->model;
11245 msurface_t *surfaces;
11246 unsigned char *update;
11247 int numsurfacelist = 0;
11251 if (r_maxsurfacelist < model->num_surfaces)
11253 r_maxsurfacelist = model->num_surfaces;
11255 Mem_Free((msurface_t **)r_surfacelist);
11256 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11259 // if the model is static it doesn't matter what value we give for
11260 // wantnormals and wanttangents, so this logic uses only rules applicable
11261 // to a model, knowing that they are meaningless otherwise
11262 if (ent == r_refdef.scene.worldentity)
11263 RSurf_ActiveWorldEntity();
11264 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11265 RSurf_ActiveModelEntity(ent, false, false, false);
11267 RSurf_ActiveModelEntity(ent, true, true, true);
11268 else if (depthonly)
11270 switch (vid.renderpath)
11272 case RENDERPATH_GL20:
11273 case RENDERPATH_D3D9:
11274 case RENDERPATH_D3D10:
11275 case RENDERPATH_D3D11:
11276 case RENDERPATH_SOFT:
11277 case RENDERPATH_GLES2:
11278 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11280 case RENDERPATH_GL13:
11281 case RENDERPATH_GL11:
11282 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11288 switch (vid.renderpath)
11290 case RENDERPATH_GL20:
11291 case RENDERPATH_D3D9:
11292 case RENDERPATH_D3D10:
11293 case RENDERPATH_D3D11:
11294 case RENDERPATH_SOFT:
11295 case RENDERPATH_GLES2:
11296 RSurf_ActiveModelEntity(ent, true, true, false);
11298 case RENDERPATH_GL13:
11299 case RENDERPATH_GL11:
11300 RSurf_ActiveModelEntity(ent, true, false, false);
11305 surfaces = model->data_surfaces;
11306 update = model->brushq1.lightmapupdateflags;
11308 // update light styles
11309 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11311 model_brush_lightstyleinfo_t *style;
11312 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11314 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11316 int *list = style->surfacelist;
11317 style->value = r_refdef.scene.lightstylevalue[style->style];
11318 for (j = 0;j < style->numsurfaces;j++)
11319 update[list[j]] = true;
11324 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11328 R_DrawDebugModel();
11329 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11333 rsurface.lightmaptexture = NULL;
11334 rsurface.deluxemaptexture = NULL;
11335 rsurface.uselightmaptexture = false;
11336 rsurface.texture = NULL;
11337 rsurface.rtlight = NULL;
11338 numsurfacelist = 0;
11339 // add visible surfaces to draw list
11340 for (i = 0;i < model->nummodelsurfaces;i++)
11341 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11342 // don't do anything if there were no surfaces
11343 if (!numsurfacelist)
11345 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11348 // update lightmaps if needed
11352 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11357 R_BuildLightMap(ent, surfaces + j);
11362 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11364 R_BuildLightMap(ent, surfaces + j);
11365 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11367 // add to stats if desired
11368 if (r_speeds.integer && !skysurfaces && !depthonly)
11370 r_refdef.stats.entities_surfaces += numsurfacelist;
11371 for (j = 0;j < numsurfacelist;j++)
11372 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11375 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11378 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11380 static texture_t texture;
11381 static msurface_t surface;
11382 const msurface_t *surfacelist = &surface;
11384 // fake enough texture and surface state to render this geometry
11386 texture.update_lastrenderframe = -1; // regenerate this texture
11387 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11388 texture.currentskinframe = skinframe;
11389 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11390 texture.offsetmapping = OFFSETMAPPING_OFF;
11391 texture.offsetscale = 1;
11392 texture.specularscalemod = 1;
11393 texture.specularpowermod = 1;
11395 surface.texture = &texture;
11396 surface.num_triangles = numtriangles;
11397 surface.num_firsttriangle = firsttriangle;
11398 surface.num_vertices = numvertices;
11399 surface.num_firstvertex = firstvertex;
11402 rsurface.texture = R_GetCurrentTexture(surface.texture);
11403 rsurface.lightmaptexture = NULL;
11404 rsurface.deluxemaptexture = NULL;
11405 rsurface.uselightmaptexture = false;
11406 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11409 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)
11411 static msurface_t surface;
11412 const msurface_t *surfacelist = &surface;
11414 // fake enough texture and surface state to render this geometry
11415 surface.texture = texture;
11416 surface.num_triangles = numtriangles;
11417 surface.num_firsttriangle = firsttriangle;
11418 surface.num_vertices = numvertices;
11419 surface.num_firstvertex = firstvertex;
11422 rsurface.texture = R_GetCurrentTexture(surface.texture);
11423 rsurface.lightmaptexture = NULL;
11424 rsurface.deluxemaptexture = NULL;
11425 rsurface.uselightmaptexture = false;
11426 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);