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_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
74 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
75 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
76 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
77 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)"};
78 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
79 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
80 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"};
81 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"};
82 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
83 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"};
84 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"};
85 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"};
86 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
87 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
88 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
89 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
90 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
91 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
92 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
93 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)"};
94 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)"};
95 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
96 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
97 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
98 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
100 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
101 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
102 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
104 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
105 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
106 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
107 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."};
108 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
109 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
110 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
111 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."};
112 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
113 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
114 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
115 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
116 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"};
117 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"};
118 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
119 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
120 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
121 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
122 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
123 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"};
125 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
126 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
127 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
128 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
129 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
130 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
131 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
132 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
134 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)"};
135 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"};
137 cvar_t r_texture_sRGB_2d = {0, "r_texture_sRGB_2d", "0", "load textures as sRGB"};
138 cvar_t r_texture_sRGB_skin_diffuse = {0, "r_texture_sRGB_skin_diffuse", "0", "load textures as sRGB"};
139 cvar_t r_texture_sRGB_skin_gloss = {0, "r_texture_sRGB_skin_gloss", "0", "load textures as sRGB"};
140 cvar_t r_texture_sRGB_skin_glow = {0, "r_texture_sRGB_skin_glow", "0", "load textures as sRGB"};
141 cvar_t r_texture_sRGB_skin_reflect = {0, "r_texture_sRGB_skin_reflect", "0", "load textures as sRGB"};
142 cvar_t r_texture_sRGB_cubemap = {0, "r_texture_sRGB_cubemap", "0", "load textures as sRGB"};
143 cvar_t r_texture_sRGB_skybox = {0, "r_texture_sRGB_skybox", "0", "load textures as sRGB"};
145 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
146 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
147 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
149 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"};
150 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"};
151 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
152 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
153 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"};
154 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)"};
155 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)"};
156 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
158 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)"};
159 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
160 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)"};
161 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
162 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)"};
163 cvar_t r_glsl_offsetmapping_reliefmapping_refinesteps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_refinesteps", "5", "relief mapping refine steps (these are a binary search executed as the last step as given by r_glsl_offsetmapping_reliefmapping_steps)"};
164 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
165 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
166 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)"};
167 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)"};
168 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)"};
169 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)"};
170 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)"};
171 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)"};
172 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)"};
173 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)"};
175 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)"};
176 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
177 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"};
178 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
179 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
180 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
182 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
183 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
184 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
185 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
187 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
188 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
189 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
190 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
191 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
192 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
193 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
195 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
196 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
197 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
198 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)"};
199 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
200 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
201 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
202 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
203 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
204 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
206 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"};
208 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"};
210 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
212 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
213 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"};
214 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
215 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
216 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
217 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
218 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)"};
219 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
220 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
222 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
223 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"};
225 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."};
227 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)"};
229 extern cvar_t v_glslgamma;
231 extern qboolean v_flipped_state;
233 static struct r_bloomstate_s
238 int bloomwidth, bloomheight;
240 textype_t texturetype;
241 int viewfbo; // used to check if r_viewfbo cvar has changed
243 int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
244 rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
245 rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
247 int screentexturewidth, screentextureheight;
248 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
250 int bloomtexturewidth, bloomtextureheight;
251 rtexture_t *texture_bloom;
253 // arrays for rendering the screen passes
254 float screentexcoord2f[8];
255 float bloomtexcoord2f[8];
256 float offsettexcoord2f[8];
258 r_viewport_t viewport;
262 r_waterstate_t r_waterstate;
264 /// shadow volume bsp struct with automatically growing nodes buffer
267 rtexture_t *r_texture_blanknormalmap;
268 rtexture_t *r_texture_white;
269 rtexture_t *r_texture_grey128;
270 rtexture_t *r_texture_black;
271 rtexture_t *r_texture_notexture;
272 rtexture_t *r_texture_whitecube;
273 rtexture_t *r_texture_normalizationcube;
274 rtexture_t *r_texture_fogattenuation;
275 rtexture_t *r_texture_fogheighttexture;
276 rtexture_t *r_texture_gammaramps;
277 unsigned int r_texture_gammaramps_serial;
278 //rtexture_t *r_texture_fogintensity;
279 rtexture_t *r_texture_reflectcube;
281 // TODO: hash lookups?
282 typedef struct cubemapinfo_s
289 int r_texture_numcubemaps;
290 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
292 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
293 unsigned int r_numqueries;
294 unsigned int r_maxqueries;
296 typedef struct r_qwskincache_s
298 char name[MAX_QPATH];
299 skinframe_t *skinframe;
303 static r_qwskincache_t *r_qwskincache;
304 static int r_qwskincache_size;
306 /// vertex coordinates for a quad that covers the screen exactly
307 extern const float r_screenvertex3f[12];
308 extern const float r_d3dscreenvertex3f[12];
309 const float r_screenvertex3f[12] =
316 const float r_d3dscreenvertex3f[12] =
324 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
327 for (i = 0;i < verts;i++)
338 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
341 for (i = 0;i < verts;i++)
351 // FIXME: move this to client?
354 if (gamemode == GAME_NEHAHRA)
356 Cvar_Set("gl_fogenable", "0");
357 Cvar_Set("gl_fogdensity", "0.2");
358 Cvar_Set("gl_fogred", "0.3");
359 Cvar_Set("gl_foggreen", "0.3");
360 Cvar_Set("gl_fogblue", "0.3");
362 r_refdef.fog_density = 0;
363 r_refdef.fog_red = 0;
364 r_refdef.fog_green = 0;
365 r_refdef.fog_blue = 0;
366 r_refdef.fog_alpha = 1;
367 r_refdef.fog_start = 0;
368 r_refdef.fog_end = 16384;
369 r_refdef.fog_height = 1<<30;
370 r_refdef.fog_fadedepth = 128;
371 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
374 static void R_BuildBlankTextures(void)
376 unsigned char data[4];
377 data[2] = 128; // normal X
378 data[1] = 128; // normal Y
379 data[0] = 255; // normal Z
380 data[3] = 128; // height
381 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
386 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
391 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
396 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
399 static void R_BuildNoTexture(void)
402 unsigned char pix[16][16][4];
403 // this makes a light grey/dark grey checkerboard texture
404 for (y = 0;y < 16;y++)
406 for (x = 0;x < 16;x++)
408 if ((y < 8) ^ (x < 8))
424 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
427 static void R_BuildWhiteCube(void)
429 unsigned char data[6*1*1*4];
430 memset(data, 255, sizeof(data));
431 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
434 static void R_BuildNormalizationCube(void)
438 vec_t s, t, intensity;
441 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
442 for (side = 0;side < 6;side++)
444 for (y = 0;y < NORMSIZE;y++)
446 for (x = 0;x < NORMSIZE;x++)
448 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
449 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
484 intensity = 127.0f / sqrt(DotProduct(v, v));
485 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
486 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
487 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
488 data[((side*64+y)*64+x)*4+3] = 255;
492 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
496 static void R_BuildFogTexture(void)
500 unsigned char data1[FOGWIDTH][4];
501 //unsigned char data2[FOGWIDTH][4];
504 r_refdef.fogmasktable_start = r_refdef.fog_start;
505 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
506 r_refdef.fogmasktable_range = r_refdef.fogrange;
507 r_refdef.fogmasktable_density = r_refdef.fog_density;
509 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
510 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
512 d = (x * r - r_refdef.fogmasktable_start);
513 if(developer_extra.integer)
514 Con_DPrintf("%f ", d);
516 if (r_fog_exp2.integer)
517 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
519 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
520 if(developer_extra.integer)
521 Con_DPrintf(" : %f ", alpha);
522 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
523 if(developer_extra.integer)
524 Con_DPrintf(" = %f\n", alpha);
525 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
528 for (x = 0;x < FOGWIDTH;x++)
530 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
535 //data2[x][0] = 255 - b;
536 //data2[x][1] = 255 - b;
537 //data2[x][2] = 255 - b;
540 if (r_texture_fogattenuation)
542 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
543 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
547 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
548 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
552 static void R_BuildFogHeightTexture(void)
554 unsigned char *inpixels;
562 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
563 if (r_refdef.fogheighttexturename[0])
564 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
567 r_refdef.fog_height_tablesize = 0;
568 if (r_texture_fogheighttexture)
569 R_FreeTexture(r_texture_fogheighttexture);
570 r_texture_fogheighttexture = NULL;
571 if (r_refdef.fog_height_table2d)
572 Mem_Free(r_refdef.fog_height_table2d);
573 r_refdef.fog_height_table2d = NULL;
574 if (r_refdef.fog_height_table1d)
575 Mem_Free(r_refdef.fog_height_table1d);
576 r_refdef.fog_height_table1d = NULL;
580 r_refdef.fog_height_tablesize = size;
581 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
582 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
583 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
585 // LordHavoc: now the magic - what is that table2d for? it is a cooked
586 // average fog color table accounting for every fog layer between a point
587 // and the camera. (Note: attenuation is handled separately!)
588 for (y = 0;y < size;y++)
590 for (x = 0;x < size;x++)
596 for (j = x;j <= y;j++)
598 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
604 for (j = x;j >= y;j--)
606 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
611 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
612 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
613 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
614 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
617 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
620 //=======================================================================================================================================================
622 static const char *builtinshaderstring =
623 #include "shader_glsl.h"
626 const char *builtinhlslshaderstring =
627 #include "shader_hlsl.h"
630 char *glslshaderstring = NULL;
631 char *hlslshaderstring = NULL;
633 //=======================================================================================================================================================
635 typedef struct shaderpermutationinfo_s
640 shaderpermutationinfo_t;
642 typedef struct shadermodeinfo_s
644 const char *vertexfilename;
645 const char *geometryfilename;
646 const char *fragmentfilename;
652 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
653 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
655 {"#define USEDIFFUSE\n", " diffuse"},
656 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
657 {"#define USEVIEWTINT\n", " viewtint"},
658 {"#define USECOLORMAPPING\n", " colormapping"},
659 {"#define USESATURATION\n", " saturation"},
660 {"#define USEFOGINSIDE\n", " foginside"},
661 {"#define USEFOGOUTSIDE\n", " fogoutside"},
662 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
663 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
664 {"#define USEGAMMARAMPS\n", " gammaramps"},
665 {"#define USECUBEFILTER\n", " cubefilter"},
666 {"#define USEGLOW\n", " glow"},
667 {"#define USEBLOOM\n", " bloom"},
668 {"#define USESPECULAR\n", " specular"},
669 {"#define USEPOSTPROCESSING\n", " postprocessing"},
670 {"#define USEREFLECTION\n", " reflection"},
671 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
672 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
673 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
674 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
675 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
676 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
677 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
678 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
679 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
680 {"#define USEALPHAKILL\n", " alphakill"},
681 {"#define USEREFLECTCUBE\n", " reflectcube"},
682 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
683 {"#define USEBOUNCEGRID\n", " bouncegrid"},
684 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
687 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
688 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
690 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
691 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
692 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
693 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
694 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
695 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
696 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
697 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
698 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
699 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
700 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
701 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
702 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
703 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
704 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
705 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
708 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
710 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
711 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
712 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
713 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
714 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
715 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
716 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
717 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
718 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
719 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
720 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
721 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
722 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
723 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
724 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
725 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
728 struct r_glsl_permutation_s;
729 typedef struct r_glsl_permutation_s
732 struct r_glsl_permutation_s *hashnext;
734 unsigned int permutation;
736 /// indicates if we have tried compiling this permutation already
738 /// 0 if compilation failed
740 // texture units assigned to each detected uniform
741 int tex_Texture_First;
742 int tex_Texture_Second;
743 int tex_Texture_GammaRamps;
744 int tex_Texture_Normal;
745 int tex_Texture_Color;
746 int tex_Texture_Gloss;
747 int tex_Texture_Glow;
748 int tex_Texture_SecondaryNormal;
749 int tex_Texture_SecondaryColor;
750 int tex_Texture_SecondaryGloss;
751 int tex_Texture_SecondaryGlow;
752 int tex_Texture_Pants;
753 int tex_Texture_Shirt;
754 int tex_Texture_FogHeightTexture;
755 int tex_Texture_FogMask;
756 int tex_Texture_Lightmap;
757 int tex_Texture_Deluxemap;
758 int tex_Texture_Attenuation;
759 int tex_Texture_Cube;
760 int tex_Texture_Refraction;
761 int tex_Texture_Reflection;
762 int tex_Texture_ShadowMap2D;
763 int tex_Texture_CubeProjection;
764 int tex_Texture_ScreenDepth;
765 int tex_Texture_ScreenNormalMap;
766 int tex_Texture_ScreenDiffuse;
767 int tex_Texture_ScreenSpecular;
768 int tex_Texture_ReflectMask;
769 int tex_Texture_ReflectCube;
770 int tex_Texture_BounceGrid;
771 /// locations of detected uniforms in program object, or -1 if not found
772 int loc_Texture_First;
773 int loc_Texture_Second;
774 int loc_Texture_GammaRamps;
775 int loc_Texture_Normal;
776 int loc_Texture_Color;
777 int loc_Texture_Gloss;
778 int loc_Texture_Glow;
779 int loc_Texture_SecondaryNormal;
780 int loc_Texture_SecondaryColor;
781 int loc_Texture_SecondaryGloss;
782 int loc_Texture_SecondaryGlow;
783 int loc_Texture_Pants;
784 int loc_Texture_Shirt;
785 int loc_Texture_FogHeightTexture;
786 int loc_Texture_FogMask;
787 int loc_Texture_Lightmap;
788 int loc_Texture_Deluxemap;
789 int loc_Texture_Attenuation;
790 int loc_Texture_Cube;
791 int loc_Texture_Refraction;
792 int loc_Texture_Reflection;
793 int loc_Texture_ShadowMap2D;
794 int loc_Texture_CubeProjection;
795 int loc_Texture_ScreenDepth;
796 int loc_Texture_ScreenNormalMap;
797 int loc_Texture_ScreenDiffuse;
798 int loc_Texture_ScreenSpecular;
799 int loc_Texture_ReflectMask;
800 int loc_Texture_ReflectCube;
801 int loc_Texture_BounceGrid;
803 int loc_BloomBlur_Parameters;
805 int loc_Color_Ambient;
806 int loc_Color_Diffuse;
807 int loc_Color_Specular;
811 int loc_DeferredColor_Ambient;
812 int loc_DeferredColor_Diffuse;
813 int loc_DeferredColor_Specular;
814 int loc_DeferredMod_Diffuse;
815 int loc_DeferredMod_Specular;
816 int loc_DistortScaleRefractReflect;
819 int loc_FogHeightFade;
821 int loc_FogPlaneViewDist;
822 int loc_FogRangeRecip;
825 int loc_LightPosition;
826 int loc_OffsetMapping_ScaleSteps;
828 int loc_ReflectColor;
829 int loc_ReflectFactor;
830 int loc_ReflectOffset;
831 int loc_RefractColor;
833 int loc_ScreenCenterRefractReflect;
834 int loc_ScreenScaleRefractReflect;
835 int loc_ScreenToDepth;
836 int loc_ShadowMap_Parameters;
837 int loc_ShadowMap_TextureScale;
838 int loc_SpecularPower;
843 int loc_ViewTintColor;
845 int loc_ModelToLight;
847 int loc_BackgroundTexMatrix;
848 int loc_ModelViewProjectionMatrix;
849 int loc_ModelViewMatrix;
850 int loc_PixelToScreenTexCoord;
851 int loc_ModelToReflectCube;
852 int loc_ShadowMapMatrix;
853 int loc_BloomColorSubtract;
854 int loc_NormalmapScrollBlend;
855 int loc_BounceGridMatrix;
856 int loc_BounceGridIntensity;
858 r_glsl_permutation_t;
860 #define SHADERPERMUTATION_HASHSIZE 256
863 // non-degradable "lightweight" shader parameters to keep the permutations simpler
864 // these can NOT degrade! only use for simple stuff
867 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
868 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
869 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
870 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
871 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
872 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
873 SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
875 #define SHADERSTATICPARMS_COUNT 7
877 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
878 static int shaderstaticparms_count = 0;
880 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
881 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
882 qboolean R_CompileShader_CheckStaticParms(void)
884 static int r_compileshader_staticparms_save[1];
885 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
886 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
889 if (r_glsl_saturation_redcompensate.integer)
890 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
891 if (r_glsl_vertextextureblend_usebothalphas.integer)
892 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
893 if (r_shadow_glossexact.integer)
894 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
895 if (r_glsl_postprocess.integer)
897 if (r_glsl_postprocess_uservec1_enable.integer)
898 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
899 if (r_glsl_postprocess_uservec2_enable.integer)
900 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
901 if (r_glsl_postprocess_uservec3_enable.integer)
902 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
903 if (r_glsl_postprocess_uservec4_enable.integer)
904 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
906 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
909 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
910 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
911 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
913 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
914 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
916 shaderstaticparms_count = 0;
919 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
920 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
921 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
922 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
923 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
924 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
925 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
928 /// information about each possible shader permutation
929 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
930 /// currently selected permutation
931 r_glsl_permutation_t *r_glsl_permutation;
932 /// storage for permutations linked in the hash table
933 memexpandablearray_t r_glsl_permutationarray;
935 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
937 //unsigned int hashdepth = 0;
938 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
939 r_glsl_permutation_t *p;
940 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
942 if (p->mode == mode && p->permutation == permutation)
944 //if (hashdepth > 10)
945 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
950 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
952 p->permutation = permutation;
953 p->hashnext = r_glsl_permutationhash[mode][hashindex];
954 r_glsl_permutationhash[mode][hashindex] = p;
955 //if (hashdepth > 10)
956 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
960 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
963 if (!filename || !filename[0])
965 if (!strcmp(filename, "glsl/default.glsl"))
967 if (!glslshaderstring)
969 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
970 if (glslshaderstring)
971 Con_DPrintf("Loading shaders from file %s...\n", filename);
973 glslshaderstring = (char *)builtinshaderstring;
975 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
976 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
979 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
982 if (printfromdisknotice)
983 Con_DPrintf("from disk %s... ", filename);
989 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
993 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
994 char *vertexstring, *geometrystring, *fragmentstring;
995 char permutationname[256];
996 int vertstrings_count = 0;
997 int geomstrings_count = 0;
998 int fragstrings_count = 0;
999 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1000 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1001 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1008 permutationname[0] = 0;
1009 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1010 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1011 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1013 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1015 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1016 if(vid.support.gl20shaders130)
1018 vertstrings_list[vertstrings_count++] = "#version 130\n";
1019 geomstrings_list[geomstrings_count++] = "#version 130\n";
1020 fragstrings_list[fragstrings_count++] = "#version 130\n";
1021 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1022 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1023 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1026 // the first pretext is which type of shader to compile as
1027 // (later these will all be bound together as a program object)
1028 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1029 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1030 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1032 // the second pretext is the mode (for example a light source)
1033 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1034 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1035 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1036 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1038 // now add all the permutation pretexts
1039 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1041 if (permutation & (1<<i))
1043 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1044 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1045 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1046 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1050 // keep line numbers correct
1051 vertstrings_list[vertstrings_count++] = "\n";
1052 geomstrings_list[geomstrings_count++] = "\n";
1053 fragstrings_list[fragstrings_count++] = "\n";
1058 R_CompileShader_AddStaticParms(mode, permutation);
1059 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1060 vertstrings_count += shaderstaticparms_count;
1061 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1062 geomstrings_count += shaderstaticparms_count;
1063 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1064 fragstrings_count += shaderstaticparms_count;
1066 // now append the shader text itself
1067 vertstrings_list[vertstrings_count++] = vertexstring;
1068 geomstrings_list[geomstrings_count++] = geometrystring;
1069 fragstrings_list[fragstrings_count++] = fragmentstring;
1071 // if any sources were NULL, clear the respective list
1073 vertstrings_count = 0;
1074 if (!geometrystring)
1075 geomstrings_count = 0;
1076 if (!fragmentstring)
1077 fragstrings_count = 0;
1079 // compile the shader program
1080 if (vertstrings_count + geomstrings_count + fragstrings_count)
1081 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1085 qglUseProgram(p->program);CHECKGLERROR
1086 // look up all the uniform variable names we care about, so we don't
1087 // have to look them up every time we set them
1089 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1090 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1091 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1092 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1093 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1094 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1095 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1096 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1097 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1098 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1099 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1100 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1101 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1102 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1103 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1104 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1105 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1106 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1107 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1108 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1109 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1110 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1111 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1112 p->loc_Texture_ScreenDepth = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1113 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1114 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1115 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1116 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1117 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1118 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1119 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1120 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1121 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1122 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1123 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1124 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1125 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1126 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1127 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1128 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1129 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1130 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1131 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1132 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1133 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1134 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1135 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1136 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1137 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1138 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1139 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1140 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1141 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1142 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1143 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1144 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1145 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1146 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1147 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1148 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1149 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1150 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1151 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1152 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1153 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1154 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1155 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1156 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1157 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1158 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1159 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1160 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1161 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1162 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1163 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1164 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1165 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1166 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1167 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1168 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1169 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1170 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1171 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1172 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1173 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1174 // initialize the samplers to refer to the texture units we use
1175 p->tex_Texture_First = -1;
1176 p->tex_Texture_Second = -1;
1177 p->tex_Texture_GammaRamps = -1;
1178 p->tex_Texture_Normal = -1;
1179 p->tex_Texture_Color = -1;
1180 p->tex_Texture_Gloss = -1;
1181 p->tex_Texture_Glow = -1;
1182 p->tex_Texture_SecondaryNormal = -1;
1183 p->tex_Texture_SecondaryColor = -1;
1184 p->tex_Texture_SecondaryGloss = -1;
1185 p->tex_Texture_SecondaryGlow = -1;
1186 p->tex_Texture_Pants = -1;
1187 p->tex_Texture_Shirt = -1;
1188 p->tex_Texture_FogHeightTexture = -1;
1189 p->tex_Texture_FogMask = -1;
1190 p->tex_Texture_Lightmap = -1;
1191 p->tex_Texture_Deluxemap = -1;
1192 p->tex_Texture_Attenuation = -1;
1193 p->tex_Texture_Cube = -1;
1194 p->tex_Texture_Refraction = -1;
1195 p->tex_Texture_Reflection = -1;
1196 p->tex_Texture_ShadowMap2D = -1;
1197 p->tex_Texture_CubeProjection = -1;
1198 p->tex_Texture_ScreenDepth = -1;
1199 p->tex_Texture_ScreenNormalMap = -1;
1200 p->tex_Texture_ScreenDiffuse = -1;
1201 p->tex_Texture_ScreenSpecular = -1;
1202 p->tex_Texture_ReflectMask = -1;
1203 p->tex_Texture_ReflectCube = -1;
1204 p->tex_Texture_BounceGrid = -1;
1206 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1207 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1208 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1209 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1210 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1211 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1212 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1213 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1214 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1215 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1216 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1217 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1218 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1219 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1220 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1221 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1222 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1223 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1224 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1225 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1226 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1227 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1228 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1229 if (p->loc_Texture_ScreenDepth >= 0) {p->tex_Texture_ScreenDepth = sampler;qglUniform1i(p->loc_Texture_ScreenDepth , sampler);sampler++;}
1230 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1231 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1232 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1233 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1234 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1235 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1237 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1240 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1244 Mem_Free(vertexstring);
1246 Mem_Free(geometrystring);
1248 Mem_Free(fragmentstring);
1251 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1253 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1254 if (r_glsl_permutation != perm)
1256 r_glsl_permutation = perm;
1257 if (!r_glsl_permutation->program)
1259 if (!r_glsl_permutation->compiled)
1260 R_GLSL_CompilePermutation(perm, mode, permutation);
1261 if (!r_glsl_permutation->program)
1263 // remove features until we find a valid permutation
1265 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1267 // reduce i more quickly whenever it would not remove any bits
1268 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1269 if (!(permutation & j))
1272 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1273 if (!r_glsl_permutation->compiled)
1274 R_GLSL_CompilePermutation(perm, mode, permutation);
1275 if (r_glsl_permutation->program)
1278 if (i >= SHADERPERMUTATION_COUNT)
1280 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1281 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1282 qglUseProgram(0);CHECKGLERROR
1283 return; // no bit left to clear, entire mode is broken
1288 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1290 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1291 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1292 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1299 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1300 extern D3DCAPS9 vid_d3d9caps;
1303 struct r_hlsl_permutation_s;
1304 typedef struct r_hlsl_permutation_s
1306 /// hash lookup data
1307 struct r_hlsl_permutation_s *hashnext;
1309 unsigned int permutation;
1311 /// indicates if we have tried compiling this permutation already
1313 /// NULL if compilation failed
1314 IDirect3DVertexShader9 *vertexshader;
1315 IDirect3DPixelShader9 *pixelshader;
1317 r_hlsl_permutation_t;
1319 typedef enum D3DVSREGISTER_e
1321 D3DVSREGISTER_TexMatrix = 0, // float4x4
1322 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1323 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1324 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1325 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1326 D3DVSREGISTER_ModelToLight = 20, // float4x4
1327 D3DVSREGISTER_EyePosition = 24,
1328 D3DVSREGISTER_FogPlane = 25,
1329 D3DVSREGISTER_LightDir = 26,
1330 D3DVSREGISTER_LightPosition = 27,
1334 typedef enum D3DPSREGISTER_e
1336 D3DPSREGISTER_Alpha = 0,
1337 D3DPSREGISTER_BloomBlur_Parameters = 1,
1338 D3DPSREGISTER_ClientTime = 2,
1339 D3DPSREGISTER_Color_Ambient = 3,
1340 D3DPSREGISTER_Color_Diffuse = 4,
1341 D3DPSREGISTER_Color_Specular = 5,
1342 D3DPSREGISTER_Color_Glow = 6,
1343 D3DPSREGISTER_Color_Pants = 7,
1344 D3DPSREGISTER_Color_Shirt = 8,
1345 D3DPSREGISTER_DeferredColor_Ambient = 9,
1346 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1347 D3DPSREGISTER_DeferredColor_Specular = 11,
1348 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1349 D3DPSREGISTER_DeferredMod_Specular = 13,
1350 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1351 D3DPSREGISTER_EyePosition = 15, // unused
1352 D3DPSREGISTER_FogColor = 16,
1353 D3DPSREGISTER_FogHeightFade = 17,
1354 D3DPSREGISTER_FogPlane = 18,
1355 D3DPSREGISTER_FogPlaneViewDist = 19,
1356 D3DPSREGISTER_FogRangeRecip = 20,
1357 D3DPSREGISTER_LightColor = 21,
1358 D3DPSREGISTER_LightDir = 22, // unused
1359 D3DPSREGISTER_LightPosition = 23,
1360 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1361 D3DPSREGISTER_PixelSize = 25,
1362 D3DPSREGISTER_ReflectColor = 26,
1363 D3DPSREGISTER_ReflectFactor = 27,
1364 D3DPSREGISTER_ReflectOffset = 28,
1365 D3DPSREGISTER_RefractColor = 29,
1366 D3DPSREGISTER_Saturation = 30,
1367 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1368 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1369 D3DPSREGISTER_ScreenToDepth = 33,
1370 D3DPSREGISTER_ShadowMap_Parameters = 34,
1371 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1372 D3DPSREGISTER_SpecularPower = 36,
1373 D3DPSREGISTER_UserVec1 = 37,
1374 D3DPSREGISTER_UserVec2 = 38,
1375 D3DPSREGISTER_UserVec3 = 39,
1376 D3DPSREGISTER_UserVec4 = 40,
1377 D3DPSREGISTER_ViewTintColor = 41,
1378 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1379 D3DPSREGISTER_BloomColorSubtract = 43,
1380 D3DPSREGISTER_ViewToLight = 44, // float4x4
1381 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1382 D3DPSREGISTER_NormalmapScrollBlend = 52,
1387 /// information about each possible shader permutation
1388 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1389 /// currently selected permutation
1390 r_hlsl_permutation_t *r_hlsl_permutation;
1391 /// storage for permutations linked in the hash table
1392 memexpandablearray_t r_hlsl_permutationarray;
1394 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1396 //unsigned int hashdepth = 0;
1397 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1398 r_hlsl_permutation_t *p;
1399 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1401 if (p->mode == mode && p->permutation == permutation)
1403 //if (hashdepth > 10)
1404 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1409 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1411 p->permutation = permutation;
1412 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1413 r_hlsl_permutationhash[mode][hashindex] = p;
1414 //if (hashdepth > 10)
1415 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1419 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1422 if (!filename || !filename[0])
1424 if (!strcmp(filename, "hlsl/default.hlsl"))
1426 if (!hlslshaderstring)
1428 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1429 if (hlslshaderstring)
1430 Con_DPrintf("Loading shaders from file %s...\n", filename);
1432 hlslshaderstring = (char *)builtinhlslshaderstring;
1434 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1435 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1436 return shaderstring;
1438 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1441 if (printfromdisknotice)
1442 Con_DPrintf("from disk %s... ", filename);
1443 return shaderstring;
1445 return shaderstring;
1449 //#include <d3dx9shader.h>
1450 //#include <d3dx9mesh.h>
1452 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1454 DWORD *vsbin = NULL;
1455 DWORD *psbin = NULL;
1456 fs_offset_t vsbinsize;
1457 fs_offset_t psbinsize;
1458 // IDirect3DVertexShader9 *vs = NULL;
1459 // IDirect3DPixelShader9 *ps = NULL;
1460 ID3DXBuffer *vslog = NULL;
1461 ID3DXBuffer *vsbuffer = NULL;
1462 ID3DXConstantTable *vsconstanttable = NULL;
1463 ID3DXBuffer *pslog = NULL;
1464 ID3DXBuffer *psbuffer = NULL;
1465 ID3DXConstantTable *psconstanttable = NULL;
1468 char temp[MAX_INPUTLINE];
1469 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1470 qboolean debugshader = gl_paranoid.integer != 0;
1471 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1472 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1475 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1476 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1478 if ((!vsbin && vertstring) || (!psbin && fragstring))
1480 const char* dllnames_d3dx9 [] =
1504 dllhandle_t d3dx9_dll = NULL;
1505 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1506 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1507 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1508 dllfunction_t d3dx9_dllfuncs[] =
1510 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1511 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1512 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1515 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1517 DWORD shaderflags = 0;
1519 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1520 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1521 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1522 if (vertstring && vertstring[0])
1526 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1527 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1528 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1529 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1532 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1535 vsbinsize = vsbuffer->GetBufferSize();
1536 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1537 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1538 vsbuffer->Release();
1542 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1543 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1547 if (fragstring && fragstring[0])
1551 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1552 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1553 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1554 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1557 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1560 psbinsize = psbuffer->GetBufferSize();
1561 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1562 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1563 psbuffer->Release();
1567 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1568 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1572 Sys_UnloadLibrary(&d3dx9_dll);
1575 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1579 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1580 if (FAILED(vsresult))
1581 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1582 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1583 if (FAILED(psresult))
1584 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1586 // free the shader data
1587 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1588 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1591 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1594 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1595 int vertstring_length = 0;
1596 int geomstring_length = 0;
1597 int fragstring_length = 0;
1599 char *vertexstring, *geometrystring, *fragmentstring;
1600 char *vertstring, *geomstring, *fragstring;
1601 char permutationname[256];
1602 char cachename[256];
1603 int vertstrings_count = 0;
1604 int geomstrings_count = 0;
1605 int fragstrings_count = 0;
1606 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1607 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1608 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1613 p->vertexshader = NULL;
1614 p->pixelshader = NULL;
1616 permutationname[0] = 0;
1618 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
1619 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1620 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1622 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1623 strlcat(cachename, "hlsl/", sizeof(cachename));
1625 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1626 vertstrings_count = 0;
1627 geomstrings_count = 0;
1628 fragstrings_count = 0;
1629 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1630 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1631 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1633 // the first pretext is which type of shader to compile as
1634 // (later these will all be bound together as a program object)
1635 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1636 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1637 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1639 // the second pretext is the mode (for example a light source)
1640 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1641 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1642 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1643 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1644 strlcat(cachename, modeinfo->name, sizeof(cachename));
1646 // now add all the permutation pretexts
1647 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1649 if (permutation & (1<<i))
1651 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1652 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1653 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1654 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1655 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1659 // keep line numbers correct
1660 vertstrings_list[vertstrings_count++] = "\n";
1661 geomstrings_list[geomstrings_count++] = "\n";
1662 fragstrings_list[fragstrings_count++] = "\n";
1667 R_CompileShader_AddStaticParms(mode, permutation);
1668 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1669 vertstrings_count += shaderstaticparms_count;
1670 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1671 geomstrings_count += shaderstaticparms_count;
1672 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1673 fragstrings_count += shaderstaticparms_count;
1675 // replace spaces in the cachename with _ characters
1676 for (i = 0;cachename[i];i++)
1677 if (cachename[i] == ' ')
1680 // now append the shader text itself
1681 vertstrings_list[vertstrings_count++] = vertexstring;
1682 geomstrings_list[geomstrings_count++] = geometrystring;
1683 fragstrings_list[fragstrings_count++] = fragmentstring;
1685 // if any sources were NULL, clear the respective list
1687 vertstrings_count = 0;
1688 if (!geometrystring)
1689 geomstrings_count = 0;
1690 if (!fragmentstring)
1691 fragstrings_count = 0;
1693 vertstring_length = 0;
1694 for (i = 0;i < vertstrings_count;i++)
1695 vertstring_length += strlen(vertstrings_list[i]);
1696 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1697 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1698 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1700 geomstring_length = 0;
1701 for (i = 0;i < geomstrings_count;i++)
1702 geomstring_length += strlen(geomstrings_list[i]);
1703 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1704 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1705 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1707 fragstring_length = 0;
1708 for (i = 0;i < fragstrings_count;i++)
1709 fragstring_length += strlen(fragstrings_list[i]);
1710 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1711 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1712 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1714 // try to load the cached shader, or generate one
1715 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1717 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1718 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1720 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1724 Mem_Free(vertstring);
1726 Mem_Free(geomstring);
1728 Mem_Free(fragstring);
1730 Mem_Free(vertexstring);
1732 Mem_Free(geometrystring);
1734 Mem_Free(fragmentstring);
1737 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1738 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1739 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);}
1740 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);}
1741 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);}
1742 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);}
1744 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1745 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1746 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);}
1747 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);}
1748 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);}
1749 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);}
1751 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1753 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1754 if (r_hlsl_permutation != perm)
1756 r_hlsl_permutation = perm;
1757 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1759 if (!r_hlsl_permutation->compiled)
1760 R_HLSL_CompilePermutation(perm, mode, permutation);
1761 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1763 // remove features until we find a valid permutation
1765 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1767 // reduce i more quickly whenever it would not remove any bits
1768 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1769 if (!(permutation & j))
1772 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1773 if (!r_hlsl_permutation->compiled)
1774 R_HLSL_CompilePermutation(perm, mode, permutation);
1775 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1778 if (i >= SHADERPERMUTATION_COUNT)
1780 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1781 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1782 return; // no bit left to clear, entire mode is broken
1786 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1787 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1789 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1790 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1791 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1795 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1797 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1798 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1799 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1800 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1803 void R_GLSL_Restart_f(void)
1805 unsigned int i, limit;
1806 if (glslshaderstring && glslshaderstring != builtinshaderstring)
1807 Mem_Free(glslshaderstring);
1808 glslshaderstring = NULL;
1809 if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1810 Mem_Free(hlslshaderstring);
1811 hlslshaderstring = NULL;
1812 switch(vid.renderpath)
1814 case RENDERPATH_D3D9:
1817 r_hlsl_permutation_t *p;
1818 r_hlsl_permutation = NULL;
1819 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1820 for (i = 0;i < limit;i++)
1822 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1824 if (p->vertexshader)
1825 IDirect3DVertexShader9_Release(p->vertexshader);
1827 IDirect3DPixelShader9_Release(p->pixelshader);
1828 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1831 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1835 case RENDERPATH_D3D10:
1836 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1838 case RENDERPATH_D3D11:
1839 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1841 case RENDERPATH_GL20:
1842 case RENDERPATH_GLES2:
1844 r_glsl_permutation_t *p;
1845 r_glsl_permutation = NULL;
1846 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1847 for (i = 0;i < limit;i++)
1849 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1851 GL_Backend_FreeProgram(p->program);
1852 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1855 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1858 case RENDERPATH_GL11:
1859 case RENDERPATH_GL13:
1860 case RENDERPATH_GLES1:
1862 case RENDERPATH_SOFT:
1867 void R_GLSL_DumpShader_f(void)
1872 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1875 FS_Print(file, "/* The engine may define the following macros:\n");
1876 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1877 for (i = 0;i < SHADERMODE_COUNT;i++)
1878 FS_Print(file, glslshadermodeinfo[i].pretext);
1879 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1880 FS_Print(file, shaderpermutationinfo[i].pretext);
1881 FS_Print(file, "*/\n");
1882 FS_Print(file, builtinshaderstring);
1884 Con_Printf("glsl/default.glsl written\n");
1887 Con_Printf("failed to write to glsl/default.glsl\n");
1889 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1892 FS_Print(file, "/* The engine may define the following macros:\n");
1893 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1894 for (i = 0;i < SHADERMODE_COUNT;i++)
1895 FS_Print(file, hlslshadermodeinfo[i].pretext);
1896 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1897 FS_Print(file, shaderpermutationinfo[i].pretext);
1898 FS_Print(file, "*/\n");
1899 FS_Print(file, builtinhlslshaderstring);
1901 Con_Printf("hlsl/default.hlsl written\n");
1904 Con_Printf("failed to write to hlsl/default.hlsl\n");
1907 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1910 texturemode = GL_MODULATE;
1911 switch (vid.renderpath)
1913 case RENDERPATH_D3D9:
1915 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))));
1916 R_Mesh_TexBind(GL20TU_FIRST , first );
1917 R_Mesh_TexBind(GL20TU_SECOND, second);
1920 case RENDERPATH_D3D10:
1921 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1923 case RENDERPATH_D3D11:
1924 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1926 case RENDERPATH_GL20:
1927 case RENDERPATH_GLES2:
1928 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))));
1929 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1930 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1932 case RENDERPATH_GL13:
1933 case RENDERPATH_GLES1:
1934 R_Mesh_TexBind(0, first );
1935 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1936 R_Mesh_TexBind(1, second);
1938 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1940 case RENDERPATH_GL11:
1941 R_Mesh_TexBind(0, first );
1943 case RENDERPATH_SOFT:
1944 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))));
1945 R_Mesh_TexBind(GL20TU_FIRST , first );
1946 R_Mesh_TexBind(GL20TU_SECOND, second);
1951 void R_SetupShader_DepthOrShadow(void)
1953 switch (vid.renderpath)
1955 case RENDERPATH_D3D9:
1957 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1960 case RENDERPATH_D3D10:
1961 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1963 case RENDERPATH_D3D11:
1964 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1966 case RENDERPATH_GL20:
1967 case RENDERPATH_GLES2:
1968 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1970 case RENDERPATH_GL13:
1971 case RENDERPATH_GLES1:
1972 R_Mesh_TexBind(0, 0);
1973 R_Mesh_TexBind(1, 0);
1975 case RENDERPATH_GL11:
1976 R_Mesh_TexBind(0, 0);
1978 case RENDERPATH_SOFT:
1979 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1984 void R_SetupShader_ShowDepth(void)
1986 switch (vid.renderpath)
1988 case RENDERPATH_D3D9:
1990 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1993 case RENDERPATH_D3D10:
1994 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1996 case RENDERPATH_D3D11:
1997 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1999 case RENDERPATH_GL20:
2000 case RENDERPATH_GLES2:
2001 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
2003 case RENDERPATH_GL13:
2004 case RENDERPATH_GLES1:
2006 case RENDERPATH_GL11:
2008 case RENDERPATH_SOFT:
2009 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
2014 extern qboolean r_shadow_usingdeferredprepass;
2015 extern cvar_t r_shadow_deferred_8bitrange;
2016 extern rtexture_t *r_shadow_attenuationgradienttexture;
2017 extern rtexture_t *r_shadow_attenuation2dtexture;
2018 extern rtexture_t *r_shadow_attenuation3dtexture;
2019 extern qboolean r_shadow_usingshadowmap2d;
2020 extern qboolean r_shadow_usingshadowmaportho;
2021 extern float r_shadow_shadowmap_texturescale[2];
2022 extern float r_shadow_shadowmap_parameters[4];
2023 extern qboolean r_shadow_shadowmapvsdct;
2024 extern qboolean r_shadow_shadowmapsampler;
2025 extern int r_shadow_shadowmappcf;
2026 extern rtexture_t *r_shadow_shadowmap2dtexture;
2027 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2028 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2029 extern matrix4x4_t r_shadow_shadowmapmatrix;
2030 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2031 extern int r_shadow_prepass_width;
2032 extern int r_shadow_prepass_height;
2033 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2034 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2035 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2036 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2037 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2039 #define BLENDFUNC_ALLOWS_COLORMOD 1
2040 #define BLENDFUNC_ALLOWS_FOG 2
2041 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2042 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2043 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2044 static int R_BlendFuncFlags(int src, int dst)
2048 // a blendfunc allows colormod if:
2049 // a) it can never keep the destination pixel invariant, or
2050 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2051 // this is to prevent unintended side effects from colormod
2053 // a blendfunc allows fog if:
2054 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2055 // this is to prevent unintended side effects from fog
2057 // these checks are the output of fogeval.pl
2059 r |= BLENDFUNC_ALLOWS_COLORMOD;
2060 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2061 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2062 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2063 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2064 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2065 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2066 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2067 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2068 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2069 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2070 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2071 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2072 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2073 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2074 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2075 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2076 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2077 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2078 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2079 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2080 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2085 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)
2087 // select a permutation of the lighting shader appropriate to this
2088 // combination of texture, entity, light source, and fogging, only use the
2089 // minimum features necessary to avoid wasting rendering time in the
2090 // fragment shader on features that are not being used
2091 unsigned int permutation = 0;
2092 unsigned int mode = 0;
2094 static float dummy_colormod[3] = {1, 1, 1};
2095 float *colormod = rsurface.colormod;
2097 matrix4x4_t tempmatrix;
2098 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2099 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2100 permutation |= SHADERPERMUTATION_ALPHAKILL;
2101 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2102 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2103 if (rsurfacepass == RSURFPASS_BACKGROUND)
2105 // distorted background
2106 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2108 mode = SHADERMODE_WATER;
2109 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2111 // this is the right thing to do for wateralpha
2112 GL_BlendFunc(GL_ONE, GL_ZERO);
2113 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2117 // this is the right thing to do for entity alpha
2118 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2119 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2122 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2124 mode = SHADERMODE_REFRACTION;
2125 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2126 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2130 mode = SHADERMODE_GENERIC;
2131 permutation |= SHADERPERMUTATION_DIFFUSE;
2132 GL_BlendFunc(GL_ONE, GL_ZERO);
2133 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2136 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2138 if (r_glsl_offsetmapping.integer)
2140 switch(rsurface.texture->offsetmapping)
2142 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2143 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2144 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2145 case OFFSETMAPPING_OFF: break;
2148 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2149 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2150 // normalmap (deferred prepass), may use alpha test on diffuse
2151 mode = SHADERMODE_DEFERREDGEOMETRY;
2152 GL_BlendFunc(GL_ONE, GL_ZERO);
2153 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2155 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2157 if (r_glsl_offsetmapping.integer)
2159 switch(rsurface.texture->offsetmapping)
2161 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2162 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2163 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2164 case OFFSETMAPPING_OFF: break;
2167 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2168 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2170 mode = SHADERMODE_LIGHTSOURCE;
2171 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2172 permutation |= SHADERPERMUTATION_CUBEFILTER;
2173 if (diffusescale > 0)
2174 permutation |= SHADERPERMUTATION_DIFFUSE;
2175 if (specularscale > 0)
2176 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2177 if (r_refdef.fogenabled)
2178 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2179 if (rsurface.texture->colormapping)
2180 permutation |= SHADERPERMUTATION_COLORMAPPING;
2181 if (r_shadow_usingshadowmap2d)
2183 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2184 if(r_shadow_shadowmapvsdct)
2185 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2187 if (r_shadow_shadowmapsampler)
2188 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2189 if (r_shadow_shadowmappcf > 1)
2190 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2191 else if (r_shadow_shadowmappcf)
2192 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2194 if (rsurface.texture->reflectmasktexture)
2195 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2196 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2197 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2199 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2201 if (r_glsl_offsetmapping.integer)
2203 switch(rsurface.texture->offsetmapping)
2205 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2206 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2207 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2208 case OFFSETMAPPING_OFF: break;
2211 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2212 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2213 // unshaded geometry (fullbright or ambient model lighting)
2214 mode = SHADERMODE_FLATCOLOR;
2215 ambientscale = diffusescale = specularscale = 0;
2216 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2217 permutation |= SHADERPERMUTATION_GLOW;
2218 if (r_refdef.fogenabled)
2219 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2220 if (rsurface.texture->colormapping)
2221 permutation |= SHADERPERMUTATION_COLORMAPPING;
2222 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2224 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2225 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2227 if (r_shadow_shadowmapsampler)
2228 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2229 if (r_shadow_shadowmappcf > 1)
2230 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2231 else if (r_shadow_shadowmappcf)
2232 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2234 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2235 permutation |= SHADERPERMUTATION_REFLECTION;
2236 if (rsurface.texture->reflectmasktexture)
2237 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2238 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2239 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2241 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2243 if (r_glsl_offsetmapping.integer)
2245 switch(rsurface.texture->offsetmapping)
2247 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2248 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2249 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2250 case OFFSETMAPPING_OFF: break;
2253 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2254 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2255 // directional model lighting
2256 mode = SHADERMODE_LIGHTDIRECTION;
2257 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2258 permutation |= SHADERPERMUTATION_GLOW;
2259 permutation |= SHADERPERMUTATION_DIFFUSE;
2260 if (specularscale > 0)
2261 permutation |= SHADERPERMUTATION_SPECULAR;
2262 if (r_refdef.fogenabled)
2263 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2264 if (rsurface.texture->colormapping)
2265 permutation |= SHADERPERMUTATION_COLORMAPPING;
2266 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2268 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2269 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2271 if (r_shadow_shadowmapsampler)
2272 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2273 if (r_shadow_shadowmappcf > 1)
2274 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2275 else if (r_shadow_shadowmappcf)
2276 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2278 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2279 permutation |= SHADERPERMUTATION_REFLECTION;
2280 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2281 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2282 if (rsurface.texture->reflectmasktexture)
2283 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2284 if (r_shadow_bouncegridtexture)
2286 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2287 if (r_shadow_bouncegriddirectional)
2288 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2290 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2291 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2293 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2295 if (r_glsl_offsetmapping.integer)
2297 switch(rsurface.texture->offsetmapping)
2299 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2300 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2301 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2302 case OFFSETMAPPING_OFF: break;
2305 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2306 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2307 // ambient model lighting
2308 mode = SHADERMODE_LIGHTDIRECTION;
2309 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2310 permutation |= SHADERPERMUTATION_GLOW;
2311 if (r_refdef.fogenabled)
2312 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2313 if (rsurface.texture->colormapping)
2314 permutation |= SHADERPERMUTATION_COLORMAPPING;
2315 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2317 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2318 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2320 if (r_shadow_shadowmapsampler)
2321 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2322 if (r_shadow_shadowmappcf > 1)
2323 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2324 else if (r_shadow_shadowmappcf)
2325 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2327 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2328 permutation |= SHADERPERMUTATION_REFLECTION;
2329 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2330 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2331 if (rsurface.texture->reflectmasktexture)
2332 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2333 if (r_shadow_bouncegridtexture)
2335 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2336 if (r_shadow_bouncegriddirectional)
2337 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2339 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2340 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2344 if (r_glsl_offsetmapping.integer)
2346 switch(rsurface.texture->offsetmapping)
2348 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2349 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2350 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2351 case OFFSETMAPPING_OFF: break;
2354 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2355 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2357 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2358 permutation |= SHADERPERMUTATION_GLOW;
2359 if (r_refdef.fogenabled)
2360 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2361 if (rsurface.texture->colormapping)
2362 permutation |= SHADERPERMUTATION_COLORMAPPING;
2363 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2365 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2366 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2368 if (r_shadow_shadowmapsampler)
2369 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2370 if (r_shadow_shadowmappcf > 1)
2371 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2372 else if (r_shadow_shadowmappcf)
2373 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2375 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2376 permutation |= SHADERPERMUTATION_REFLECTION;
2377 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2378 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2379 if (rsurface.texture->reflectmasktexture)
2380 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2381 if (FAKELIGHT_ENABLED)
2383 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2384 mode = SHADERMODE_FAKELIGHT;
2385 permutation |= SHADERPERMUTATION_DIFFUSE;
2386 if (specularscale > 0)
2387 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2389 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2391 // deluxemapping (light direction texture)
2392 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2393 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2395 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2396 permutation |= SHADERPERMUTATION_DIFFUSE;
2397 if (specularscale > 0)
2398 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2400 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2402 // fake deluxemapping (uniform light direction in tangentspace)
2403 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2404 permutation |= SHADERPERMUTATION_DIFFUSE;
2405 if (specularscale > 0)
2406 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2408 else if (rsurface.uselightmaptexture)
2410 // ordinary lightmapping (q1bsp, q3bsp)
2411 mode = SHADERMODE_LIGHTMAP;
2415 // ordinary vertex coloring (q3bsp)
2416 mode = SHADERMODE_VERTEXCOLOR;
2418 if (r_shadow_bouncegridtexture)
2420 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2421 if (r_shadow_bouncegriddirectional)
2422 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2424 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2425 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2427 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2428 colormod = dummy_colormod;
2429 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2430 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2431 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2432 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2433 switch(vid.renderpath)
2435 case RENDERPATH_D3D9:
2437 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);
2438 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2439 R_SetupShader_SetPermutationHLSL(mode, permutation);
2440 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2441 if (mode == SHADERMODE_LIGHTSOURCE)
2443 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2444 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2448 if (mode == SHADERMODE_LIGHTDIRECTION)
2450 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2453 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2454 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2455 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2456 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2457 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2459 if (mode == SHADERMODE_LIGHTSOURCE)
2461 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2462 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2463 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2464 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2465 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2467 // additive passes are only darkened by fog, not tinted
2468 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2469 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2473 if (mode == SHADERMODE_FLATCOLOR)
2475 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2477 else if (mode == SHADERMODE_LIGHTDIRECTION)
2479 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]);
2480 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[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] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * 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);
2484 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2485 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2489 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2490 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2491 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);
2492 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);
2493 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2495 // additive passes are only darkened by fog, not tinted
2496 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2497 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2499 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2500 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);
2501 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2502 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2503 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2504 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2505 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2506 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2507 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2508 if (mode == SHADERMODE_WATER)
2509 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2511 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2512 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2513 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2514 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));
2515 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2516 if (rsurface.texture->pantstexture)
2517 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2519 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2520 if (rsurface.texture->shirttexture)
2521 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2523 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2524 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2525 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2526 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2527 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2528 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2529 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2530 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2531 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2532 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2534 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2535 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2537 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2538 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2539 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2540 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2541 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2542 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2543 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2544 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2545 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2546 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2547 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2548 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2549 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2550 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2551 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2552 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2553 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2554 if (rsurfacepass == RSURFPASS_BACKGROUND)
2556 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2557 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2558 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2562 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2564 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2565 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2566 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2567 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2568 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2570 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2571 if (rsurface.rtlight)
2573 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2574 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2579 case RENDERPATH_D3D10:
2580 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2582 case RENDERPATH_D3D11:
2583 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2585 case RENDERPATH_GL20:
2586 case RENDERPATH_GLES2:
2587 if (!vid.useinterleavedarrays)
2589 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);
2590 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2591 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2592 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2593 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2594 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2595 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2596 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2600 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);
2601 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2603 R_SetupShader_SetPermutationGLSL(mode, permutation);
2604 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2605 if (mode == SHADERMODE_LIGHTSOURCE)
2607 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2608 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2609 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2610 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2611 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2612 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);
2614 // additive passes are only darkened by fog, not tinted
2615 if (r_glsl_permutation->loc_FogColor >= 0)
2616 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2617 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2621 if (mode == SHADERMODE_FLATCOLOR)
2623 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2625 else if (mode == SHADERMODE_LIGHTDIRECTION)
2627 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]);
2628 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]);
2629 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);
2630 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);
2631 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);
2632 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]);
2633 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]);
2637 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]);
2638 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]);
2639 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);
2640 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);
2641 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);
2643 // additive passes are only darkened by fog, not tinted
2644 if (r_glsl_permutation->loc_FogColor >= 0)
2646 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2647 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2649 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2651 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);
2652 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]);
2653 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]);
2654 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]);
2655 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]);
2656 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2657 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2658 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2659 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]);
2661 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2662 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2663 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2664 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]);
2665 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]);
2667 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2668 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));
2669 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2670 if (r_glsl_permutation->loc_Color_Pants >= 0)
2672 if (rsurface.texture->pantstexture)
2673 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2675 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2677 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2679 if (rsurface.texture->shirttexture)
2680 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2682 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2684 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]);
2685 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2686 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2687 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2688 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2689 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2690 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2691 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2692 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2694 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]);
2695 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2696 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);}
2697 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2699 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2700 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2701 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2702 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2703 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2704 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2705 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2706 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2707 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2708 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2709 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2710 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2711 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2712 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2713 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);
2714 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2715 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2716 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2717 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2718 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2719 if (rsurfacepass == RSURFPASS_BACKGROUND)
2721 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);
2722 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);
2723 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);
2727 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);
2729 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2730 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2731 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2732 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2733 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2735 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
2736 if (rsurface.rtlight)
2738 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2739 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2742 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2745 case RENDERPATH_GL11:
2746 case RENDERPATH_GL13:
2747 case RENDERPATH_GLES1:
2749 case RENDERPATH_SOFT:
2750 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);
2751 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2752 R_SetupShader_SetPermutationSoft(mode, permutation);
2753 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2754 if (mode == SHADERMODE_LIGHTSOURCE)
2756 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2757 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2758 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2759 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2760 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2761 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2763 // additive passes are only darkened by fog, not tinted
2764 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2765 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2769 if (mode == SHADERMODE_FLATCOLOR)
2771 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2773 else if (mode == SHADERMODE_LIGHTDIRECTION)
2775 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]);
2776 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2777 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);
2778 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);
2779 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2780 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]);
2781 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2785 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2786 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2787 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);
2788 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);
2789 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2791 // additive passes are only darkened by fog, not tinted
2792 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2793 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2795 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2796 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);
2797 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2798 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2799 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]);
2800 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]);
2801 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2802 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2803 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2804 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2806 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2807 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2808 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2809 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2810 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]);
2812 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2813 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));
2814 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2815 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2817 if (rsurface.texture->pantstexture)
2818 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2820 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2822 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2824 if (rsurface.texture->shirttexture)
2825 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2827 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2829 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2830 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2831 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2832 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2833 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2834 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2835 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2836 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2837 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2839 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2840 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2842 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2843 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2844 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2845 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2846 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2847 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2848 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2849 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2850 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2851 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2852 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2853 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2854 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2855 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2856 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2857 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2858 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2859 if (rsurfacepass == RSURFPASS_BACKGROUND)
2861 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2862 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2863 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2867 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2869 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2870 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2871 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2872 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2873 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2875 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2876 if (rsurface.rtlight)
2878 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2879 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2886 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2888 // select a permutation of the lighting shader appropriate to this
2889 // combination of texture, entity, light source, and fogging, only use the
2890 // minimum features necessary to avoid wasting rendering time in the
2891 // fragment shader on features that are not being used
2892 unsigned int permutation = 0;
2893 unsigned int mode = 0;
2894 const float *lightcolorbase = rtlight->currentcolor;
2895 float ambientscale = rtlight->ambientscale;
2896 float diffusescale = rtlight->diffusescale;
2897 float specularscale = rtlight->specularscale;
2898 // this is the location of the light in view space
2899 vec3_t viewlightorigin;
2900 // this transforms from view space (camera) to light space (cubemap)
2901 matrix4x4_t viewtolight;
2902 matrix4x4_t lighttoview;
2903 float viewtolight16f[16];
2904 float range = 1.0f / r_shadow_deferred_8bitrange.value;
2906 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2907 if (rtlight->currentcubemap != r_texture_whitecube)
2908 permutation |= SHADERPERMUTATION_CUBEFILTER;
2909 if (diffusescale > 0)
2910 permutation |= SHADERPERMUTATION_DIFFUSE;
2911 if (specularscale > 0 && r_shadow_gloss.integer > 0)
2912 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2913 if (r_shadow_usingshadowmap2d)
2915 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2916 if (r_shadow_shadowmapvsdct)
2917 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2919 if (r_shadow_shadowmapsampler)
2920 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2921 if (r_shadow_shadowmappcf > 1)
2922 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2923 else if (r_shadow_shadowmappcf)
2924 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2926 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2927 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2928 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2929 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2930 switch(vid.renderpath)
2932 case RENDERPATH_D3D9:
2934 R_SetupShader_SetPermutationHLSL(mode, permutation);
2935 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2936 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2937 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2938 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2939 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2940 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2941 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2942 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2943 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2944 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2946 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2947 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
2948 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2949 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2950 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
2951 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2954 case RENDERPATH_D3D10:
2955 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2957 case RENDERPATH_D3D11:
2958 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2960 case RENDERPATH_GL20:
2961 case RENDERPATH_GLES2:
2962 R_SetupShader_SetPermutationGLSL(mode, permutation);
2963 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2964 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
2965 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);
2966 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);
2967 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);
2968 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]);
2969 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]);
2970 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));
2971 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]);
2972 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
2974 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2975 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2976 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2977 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2978 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
2979 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2981 case RENDERPATH_GL11:
2982 case RENDERPATH_GL13:
2983 case RENDERPATH_GLES1:
2985 case RENDERPATH_SOFT:
2986 R_SetupShader_SetPermutationGLSL(mode, permutation);
2987 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2988 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
2989 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2990 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2991 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2992 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2993 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]);
2994 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));
2995 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2996 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2998 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2999 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
3000 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3001 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3002 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
3003 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3008 #define SKINFRAME_HASH 1024
3012 int loadsequence; // incremented each level change
3013 memexpandablearray_t array;
3014 skinframe_t *hash[SKINFRAME_HASH];
3017 r_skinframe_t r_skinframe;
3019 void R_SkinFrame_PrepareForPurge(void)
3021 r_skinframe.loadsequence++;
3022 // wrap it without hitting zero
3023 if (r_skinframe.loadsequence >= 200)
3024 r_skinframe.loadsequence = 1;
3027 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3031 // mark the skinframe as used for the purging code
3032 skinframe->loadsequence = r_skinframe.loadsequence;
3035 void R_SkinFrame_Purge(void)
3039 for (i = 0;i < SKINFRAME_HASH;i++)
3041 for (s = r_skinframe.hash[i];s;s = s->next)
3043 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3045 if (s->merged == s->base)
3047 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3048 R_PurgeTexture(s->stain );s->stain = NULL;
3049 R_PurgeTexture(s->merged);s->merged = NULL;
3050 R_PurgeTexture(s->base );s->base = NULL;
3051 R_PurgeTexture(s->pants );s->pants = NULL;
3052 R_PurgeTexture(s->shirt );s->shirt = NULL;
3053 R_PurgeTexture(s->nmap );s->nmap = NULL;
3054 R_PurgeTexture(s->gloss );s->gloss = NULL;
3055 R_PurgeTexture(s->glow );s->glow = NULL;
3056 R_PurgeTexture(s->fog );s->fog = NULL;
3057 R_PurgeTexture(s->reflect);s->reflect = NULL;
3058 s->loadsequence = 0;
3064 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3066 char basename[MAX_QPATH];
3068 Image_StripImageExtension(name, basename, sizeof(basename));
3070 if( last == NULL ) {
3072 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3073 item = r_skinframe.hash[hashindex];
3078 // linearly search through the hash bucket
3079 for( ; item ; item = item->next ) {
3080 if( !strcmp( item->basename, basename ) ) {
3087 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3091 char basename[MAX_QPATH];
3093 Image_StripImageExtension(name, basename, sizeof(basename));
3095 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3096 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3097 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3101 rtexture_t *dyntexture;
3102 // check whether its a dynamic texture
3103 dyntexture = CL_GetDynTexture( basename );
3104 if (!add && !dyntexture)
3106 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3107 memset(item, 0, sizeof(*item));
3108 strlcpy(item->basename, basename, sizeof(item->basename));
3109 item->base = dyntexture; // either NULL or dyntexture handle
3110 item->textureflags = textureflags;
3111 item->comparewidth = comparewidth;
3112 item->compareheight = compareheight;
3113 item->comparecrc = comparecrc;
3114 item->next = r_skinframe.hash[hashindex];
3115 r_skinframe.hash[hashindex] = item;
3117 else if( item->base == NULL )
3119 rtexture_t *dyntexture;
3120 // check whether its a dynamic texture
3121 // 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]
3122 dyntexture = CL_GetDynTexture( basename );
3123 item->base = dyntexture; // either NULL or dyntexture handle
3126 R_SkinFrame_MarkUsed(item);
3130 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3132 unsigned long long avgcolor[5], wsum; \
3140 for(pix = 0; pix < cnt; ++pix) \
3143 for(comp = 0; comp < 3; ++comp) \
3145 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3148 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3150 for(comp = 0; comp < 3; ++comp) \
3151 avgcolor[comp] += getpixel * w; \
3154 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3155 avgcolor[4] += getpixel; \
3157 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3159 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3160 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3161 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3162 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3165 extern cvar_t gl_picmip;
3166 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3169 unsigned char *pixels;
3170 unsigned char *bumppixels;
3171 unsigned char *basepixels = NULL;
3172 int basepixels_width = 0;
3173 int basepixels_height = 0;
3174 skinframe_t *skinframe;
3175 rtexture_t *ddsbase = NULL;
3176 qboolean ddshasalpha = false;
3177 float ddsavgcolor[4];
3178 char basename[MAX_QPATH];
3179 int miplevel = R_PicmipForFlags(textureflags);
3180 int savemiplevel = miplevel;
3183 if (cls.state == ca_dedicated)
3186 // return an existing skinframe if already loaded
3187 // if loading of the first image fails, don't make a new skinframe as it
3188 // would cause all future lookups of this to be missing
3189 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3190 if (skinframe && skinframe->base)
3193 Image_StripImageExtension(name, basename, sizeof(basename));
3195 // check for DDS texture file first
3196 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3198 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3199 if (basepixels == NULL)
3203 // FIXME handle miplevel
3205 if (developer_loading.integer)
3206 Con_Printf("loading skin \"%s\"\n", name);
3208 // we've got some pixels to store, so really allocate this new texture now
3210 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3211 skinframe->stain = NULL;
3212 skinframe->merged = NULL;
3213 skinframe->base = NULL;
3214 skinframe->pants = NULL;
3215 skinframe->shirt = NULL;
3216 skinframe->nmap = NULL;
3217 skinframe->gloss = NULL;
3218 skinframe->glow = NULL;
3219 skinframe->fog = NULL;
3220 skinframe->reflect = NULL;
3221 skinframe->hasalpha = false;
3225 skinframe->base = ddsbase;
3226 skinframe->hasalpha = ddshasalpha;
3227 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3228 if (r_loadfog && skinframe->hasalpha)
3229 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3230 //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]);
3234 basepixels_width = image_width;
3235 basepixels_height = image_height;
3236 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, r_texture_sRGB_skin_diffuse.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3237 if (textureflags & TEXF_ALPHA)
3239 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3241 if (basepixels[j] < 255)
3243 skinframe->hasalpha = true;
3247 if (r_loadfog && skinframe->hasalpha)
3249 // has transparent pixels
3250 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3251 for (j = 0;j < image_width * image_height * 4;j += 4)
3256 pixels[j+3] = basepixels[j+3];
3258 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);
3262 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3263 //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]);
3264 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3265 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
3266 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3267 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
3272 mymiplevel = savemiplevel;
3273 if (r_loadnormalmap)
3274 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);
3275 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3277 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3278 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3279 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3280 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3283 // _norm is the name used by tenebrae and has been adopted as standard
3284 if (r_loadnormalmap && skinframe->nmap == NULL)
3286 mymiplevel = savemiplevel;
3287 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3289 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);
3293 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3295 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3296 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3297 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);
3299 Mem_Free(bumppixels);
3301 else if (r_shadow_bumpscale_basetexture.value > 0)
3303 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3304 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3305 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);
3308 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3309 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
3312 // _luma is supported only for tenebrae compatibility
3313 // _glow is the preferred name
3314 mymiplevel = savemiplevel;
3315 if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false, false, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, false, &mymiplevel))))
3317 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, r_texture_sRGB_skin_glow.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3318 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3319 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
3320 Mem_Free(pixels);pixels = NULL;
3323 mymiplevel = savemiplevel;
3324 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3326 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, r_texture_sRGB_skin_gloss.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3327 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3328 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
3333 mymiplevel = savemiplevel;
3334 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3336 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, r_texture_sRGB_skin_diffuse.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3337 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3338 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
3343 mymiplevel = savemiplevel;
3344 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3346 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, r_texture_sRGB_skin_diffuse.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3347 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3348 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
3353 mymiplevel = savemiplevel;
3354 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3356 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, r_texture_sRGB_skin_reflect.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3357 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3358 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
3364 Mem_Free(basepixels);
3369 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3370 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3373 unsigned char *temp1, *temp2;
3374 skinframe_t *skinframe;
3376 if (cls.state == ca_dedicated)
3379 // if already loaded just return it, otherwise make a new skinframe
3380 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3381 if (skinframe && skinframe->base)
3384 skinframe->stain = NULL;
3385 skinframe->merged = NULL;
3386 skinframe->base = NULL;
3387 skinframe->pants = NULL;
3388 skinframe->shirt = NULL;
3389 skinframe->nmap = NULL;
3390 skinframe->gloss = NULL;
3391 skinframe->glow = NULL;
3392 skinframe->fog = NULL;
3393 skinframe->reflect = NULL;
3394 skinframe->hasalpha = false;
3396 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3400 if (developer_loading.integer)
3401 Con_Printf("loading 32bit skin \"%s\"\n", name);
3403 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3405 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3406 temp2 = temp1 + width * height * 4;
3407 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3408 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);
3411 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3412 if (textureflags & TEXF_ALPHA)
3414 for (i = 3;i < width * height * 4;i += 4)
3416 if (skindata[i] < 255)
3418 skinframe->hasalpha = true;
3422 if (r_loadfog && skinframe->hasalpha)
3424 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3425 memcpy(fogpixels, skindata, width * height * 4);
3426 for (i = 0;i < width * height * 4;i += 4)
3427 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3428 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3429 Mem_Free(fogpixels);
3433 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3434 //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]);
3439 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3443 skinframe_t *skinframe;
3445 if (cls.state == ca_dedicated)
3448 // if already loaded just return it, otherwise make a new skinframe
3449 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3450 if (skinframe && skinframe->base)
3453 skinframe->stain = NULL;
3454 skinframe->merged = NULL;
3455 skinframe->base = NULL;
3456 skinframe->pants = NULL;
3457 skinframe->shirt = NULL;
3458 skinframe->nmap = NULL;
3459 skinframe->gloss = NULL;
3460 skinframe->glow = NULL;
3461 skinframe->fog = NULL;
3462 skinframe->reflect = NULL;
3463 skinframe->hasalpha = false;
3465 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3469 if (developer_loading.integer)
3470 Con_Printf("loading quake skin \"%s\"\n", name);
3472 // 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)
3473 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3474 memcpy(skinframe->qpixels, skindata, width*height);
3475 skinframe->qwidth = width;
3476 skinframe->qheight = height;
3479 for (i = 0;i < width * height;i++)
3480 featuresmask |= palette_featureflags[skindata[i]];
3482 skinframe->hasalpha = false;
3483 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3484 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3485 skinframe->qgeneratemerged = true;
3486 skinframe->qgeneratebase = skinframe->qhascolormapping;
3487 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3489 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3490 //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]);
3495 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3499 unsigned char *skindata;
3501 if (!skinframe->qpixels)
3504 if (!skinframe->qhascolormapping)
3505 colormapped = false;
3509 if (!skinframe->qgeneratebase)
3514 if (!skinframe->qgeneratemerged)
3518 width = skinframe->qwidth;
3519 height = skinframe->qheight;
3520 skindata = skinframe->qpixels;
3522 if (skinframe->qgeneratenmap)
3524 unsigned char *temp1, *temp2;
3525 skinframe->qgeneratenmap = false;
3526 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3527 temp2 = temp1 + width * height * 4;
3528 // use either a custom palette or the quake palette
3529 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3530 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3531 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);
3535 if (skinframe->qgenerateglow)
3537 skinframe->qgenerateglow = false;
3538 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3543 skinframe->qgeneratebase = false;
3544 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);
3545 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3546 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3550 skinframe->qgeneratemerged = false;
3551 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);
3554 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3556 Mem_Free(skinframe->qpixels);
3557 skinframe->qpixels = NULL;
3561 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)
3564 skinframe_t *skinframe;
3566 if (cls.state == ca_dedicated)
3569 // if already loaded just return it, otherwise make a new skinframe
3570 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3571 if (skinframe && skinframe->base)
3574 skinframe->stain = NULL;
3575 skinframe->merged = NULL;
3576 skinframe->base = NULL;
3577 skinframe->pants = NULL;
3578 skinframe->shirt = NULL;
3579 skinframe->nmap = NULL;
3580 skinframe->gloss = NULL;
3581 skinframe->glow = NULL;
3582 skinframe->fog = NULL;
3583 skinframe->reflect = NULL;
3584 skinframe->hasalpha = false;
3586 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3590 if (developer_loading.integer)
3591 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3593 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3594 if (textureflags & TEXF_ALPHA)
3596 for (i = 0;i < width * height;i++)
3598 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3600 skinframe->hasalpha = true;
3604 if (r_loadfog && skinframe->hasalpha)
3605 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3608 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3609 //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]);
3614 skinframe_t *R_SkinFrame_LoadMissing(void)
3616 skinframe_t *skinframe;
3618 if (cls.state == ca_dedicated)
3621 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3622 skinframe->stain = NULL;
3623 skinframe->merged = NULL;
3624 skinframe->base = NULL;
3625 skinframe->pants = NULL;
3626 skinframe->shirt = NULL;
3627 skinframe->nmap = NULL;
3628 skinframe->gloss = NULL;
3629 skinframe->glow = NULL;
3630 skinframe->fog = NULL;
3631 skinframe->reflect = NULL;
3632 skinframe->hasalpha = false;
3634 skinframe->avgcolor[0] = rand() / RAND_MAX;
3635 skinframe->avgcolor[1] = rand() / RAND_MAX;
3636 skinframe->avgcolor[2] = rand() / RAND_MAX;
3637 skinframe->avgcolor[3] = 1;
3642 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3643 typedef struct suffixinfo_s
3646 qboolean flipx, flipy, flipdiagonal;
3649 static suffixinfo_t suffix[3][6] =
3652 {"px", false, false, false},
3653 {"nx", false, false, false},
3654 {"py", false, false, false},
3655 {"ny", false, false, false},
3656 {"pz", false, false, false},
3657 {"nz", false, false, false}
3660 {"posx", false, false, false},
3661 {"negx", false, false, false},
3662 {"posy", false, false, false},
3663 {"negy", false, false, false},
3664 {"posz", false, false, false},
3665 {"negz", false, false, false}
3668 {"rt", true, false, true},
3669 {"lf", false, true, true},
3670 {"ft", true, true, false},
3671 {"bk", false, false, false},
3672 {"up", true, false, true},
3673 {"dn", true, false, true}
3677 static int componentorder[4] = {0, 1, 2, 3};
3679 rtexture_t *R_LoadCubemap(const char *basename)
3681 int i, j, cubemapsize;
3682 unsigned char *cubemappixels, *image_buffer;
3683 rtexture_t *cubemaptexture;
3685 // must start 0 so the first loadimagepixels has no requested width/height
3687 cubemappixels = NULL;
3688 cubemaptexture = NULL;
3689 // keep trying different suffix groups (posx, px, rt) until one loads
3690 for (j = 0;j < 3 && !cubemappixels;j++)
3692 // load the 6 images in the suffix group
3693 for (i = 0;i < 6;i++)
3695 // generate an image name based on the base and and suffix
3696 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3698 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3700 // an image loaded, make sure width and height are equal
3701 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3703 // if this is the first image to load successfully, allocate the cubemap memory
3704 if (!cubemappixels && image_width >= 1)
3706 cubemapsize = image_width;
3707 // note this clears to black, so unavailable sides are black
3708 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3710 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3712 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);
3715 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3717 Mem_Free(image_buffer);
3721 // if a cubemap loaded, upload it
3724 if (developer_loading.integer)
3725 Con_Printf("loading cubemap \"%s\"\n", basename);
3727 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, r_texture_sRGB_cubemap.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3728 Mem_Free(cubemappixels);
3732 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3733 if (developer_loading.integer)
3735 Con_Printf("(tried tried images ");
3736 for (j = 0;j < 3;j++)
3737 for (i = 0;i < 6;i++)
3738 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3739 Con_Print(" and was unable to find any of them).\n");
3742 return cubemaptexture;
3745 rtexture_t *R_GetCubemap(const char *basename)
3748 for (i = 0;i < r_texture_numcubemaps;i++)
3749 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3750 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3751 if (i >= MAX_CUBEMAPS)
3752 return r_texture_whitecube;
3753 r_texture_numcubemaps++;
3754 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3755 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3756 return r_texture_cubemaps[i].texture;
3759 void R_FreeCubemaps(void)
3762 for (i = 0;i < r_texture_numcubemaps;i++)
3764 if (developer_loading.integer)
3765 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3766 if (r_texture_cubemaps[i].texture)
3767 R_FreeTexture(r_texture_cubemaps[i].texture);
3769 r_texture_numcubemaps = 0;
3772 void R_Main_FreeViewCache(void)
3774 if (r_refdef.viewcache.entityvisible)
3775 Mem_Free(r_refdef.viewcache.entityvisible);
3776 if (r_refdef.viewcache.world_pvsbits)
3777 Mem_Free(r_refdef.viewcache.world_pvsbits);
3778 if (r_refdef.viewcache.world_leafvisible)
3779 Mem_Free(r_refdef.viewcache.world_leafvisible);
3780 if (r_refdef.viewcache.world_surfacevisible)
3781 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3782 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3785 void R_Main_ResizeViewCache(void)
3787 int numentities = r_refdef.scene.numentities;
3788 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3789 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3790 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3791 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3792 if (r_refdef.viewcache.maxentities < numentities)
3794 r_refdef.viewcache.maxentities = numentities;
3795 if (r_refdef.viewcache.entityvisible)
3796 Mem_Free(r_refdef.viewcache.entityvisible);
3797 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3799 if (r_refdef.viewcache.world_numclusters != numclusters)
3801 r_refdef.viewcache.world_numclusters = numclusters;
3802 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3803 if (r_refdef.viewcache.world_pvsbits)
3804 Mem_Free(r_refdef.viewcache.world_pvsbits);
3805 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3807 if (r_refdef.viewcache.world_numleafs != numleafs)
3809 r_refdef.viewcache.world_numleafs = numleafs;
3810 if (r_refdef.viewcache.world_leafvisible)
3811 Mem_Free(r_refdef.viewcache.world_leafvisible);
3812 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3814 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3816 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3817 if (r_refdef.viewcache.world_surfacevisible)
3818 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3819 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3823 extern rtexture_t *loadingscreentexture;
3824 void gl_main_start(void)
3826 loadingscreentexture = NULL;
3827 r_texture_blanknormalmap = NULL;
3828 r_texture_white = NULL;
3829 r_texture_grey128 = NULL;
3830 r_texture_black = NULL;
3831 r_texture_whitecube = NULL;
3832 r_texture_normalizationcube = NULL;
3833 r_texture_fogattenuation = NULL;
3834 r_texture_fogheighttexture = NULL;
3835 r_texture_gammaramps = NULL;
3836 r_texture_numcubemaps = 0;
3838 r_loaddds = r_texture_dds_load.integer != 0;
3839 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3841 switch(vid.renderpath)
3843 case RENDERPATH_GL20:
3844 case RENDERPATH_D3D9:
3845 case RENDERPATH_D3D10:
3846 case RENDERPATH_D3D11:
3847 case RENDERPATH_SOFT:
3848 case RENDERPATH_GLES2:
3849 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3850 Cvar_SetValueQuick(&gl_combine, 1);
3851 Cvar_SetValueQuick(&r_glsl, 1);
3852 r_loadnormalmap = true;
3856 case RENDERPATH_GL13:
3857 case RENDERPATH_GLES1:
3858 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3859 Cvar_SetValueQuick(&gl_combine, 1);
3860 Cvar_SetValueQuick(&r_glsl, 0);
3861 r_loadnormalmap = false;
3862 r_loadgloss = false;
3865 case RENDERPATH_GL11:
3866 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3867 Cvar_SetValueQuick(&gl_combine, 0);
3868 Cvar_SetValueQuick(&r_glsl, 0);
3869 r_loadnormalmap = false;
3870 r_loadgloss = false;
3876 R_FrameData_Reset();
3880 memset(r_queries, 0, sizeof(r_queries));
3882 r_qwskincache = NULL;
3883 r_qwskincache_size = 0;
3885 // due to caching of texture_t references, the collision cache must be reset
3886 Collision_Cache_Reset(true);
3888 // set up r_skinframe loading system for textures
3889 memset(&r_skinframe, 0, sizeof(r_skinframe));
3890 r_skinframe.loadsequence = 1;
3891 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3893 r_main_texturepool = R_AllocTexturePool();
3894 R_BuildBlankTextures();
3896 if (vid.support.arb_texture_cube_map)
3899 R_BuildNormalizationCube();
3901 r_texture_fogattenuation = NULL;
3902 r_texture_fogheighttexture = NULL;
3903 r_texture_gammaramps = NULL;
3904 //r_texture_fogintensity = NULL;
3905 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3906 memset(&r_waterstate, 0, sizeof(r_waterstate));
3907 r_glsl_permutation = NULL;
3908 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3909 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3910 glslshaderstring = NULL;
3912 r_hlsl_permutation = NULL;
3913 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3914 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3916 hlslshaderstring = NULL;
3917 memset(&r_svbsp, 0, sizeof (r_svbsp));
3919 r_refdef.fogmasktable_density = 0;
3922 void gl_main_shutdown(void)
3925 R_FrameData_Reset();
3927 R_Main_FreeViewCache();
3929 switch(vid.renderpath)
3931 case RENDERPATH_GL11:
3932 case RENDERPATH_GL13:
3933 case RENDERPATH_GL20:
3934 case RENDERPATH_GLES1:
3935 case RENDERPATH_GLES2:
3937 qglDeleteQueriesARB(r_maxqueries, r_queries);
3939 case RENDERPATH_D3D9:
3940 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3942 case RENDERPATH_D3D10:
3943 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3945 case RENDERPATH_D3D11:
3946 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3948 case RENDERPATH_SOFT:
3954 memset(r_queries, 0, sizeof(r_queries));
3956 r_qwskincache = NULL;
3957 r_qwskincache_size = 0;
3959 // clear out the r_skinframe state
3960 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3961 memset(&r_skinframe, 0, sizeof(r_skinframe));
3964 Mem_Free(r_svbsp.nodes);
3965 memset(&r_svbsp, 0, sizeof (r_svbsp));
3966 R_FreeTexturePool(&r_main_texturepool);
3967 loadingscreentexture = NULL;
3968 r_texture_blanknormalmap = NULL;
3969 r_texture_white = NULL;
3970 r_texture_grey128 = NULL;
3971 r_texture_black = NULL;
3972 r_texture_whitecube = NULL;
3973 r_texture_normalizationcube = NULL;
3974 r_texture_fogattenuation = NULL;
3975 r_texture_fogheighttexture = NULL;
3976 r_texture_gammaramps = NULL;
3977 r_texture_numcubemaps = 0;
3978 //r_texture_fogintensity = NULL;
3979 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3980 memset(&r_waterstate, 0, sizeof(r_waterstate));
3983 r_glsl_permutation = NULL;
3984 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3985 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3986 glslshaderstring = NULL;
3988 r_hlsl_permutation = NULL;
3989 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3990 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3992 hlslshaderstring = NULL;
3995 extern void CL_ParseEntityLump(char *entitystring);
3996 void gl_main_newmap(void)
3998 // FIXME: move this code to client
3999 char *entities, entname[MAX_QPATH];
4001 Mem_Free(r_qwskincache);
4002 r_qwskincache = NULL;
4003 r_qwskincache_size = 0;
4006 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4007 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4009 CL_ParseEntityLump(entities);
4013 if (cl.worldmodel->brush.entities)
4014 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4016 R_Main_FreeViewCache();
4018 R_FrameData_Reset();
4021 void GL_Main_Init(void)
4023 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4025 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4026 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4027 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4028 if (gamemode == GAME_NEHAHRA)
4030 Cvar_RegisterVariable (&gl_fogenable);
4031 Cvar_RegisterVariable (&gl_fogdensity);
4032 Cvar_RegisterVariable (&gl_fogred);
4033 Cvar_RegisterVariable (&gl_foggreen);
4034 Cvar_RegisterVariable (&gl_fogblue);
4035 Cvar_RegisterVariable (&gl_fogstart);
4036 Cvar_RegisterVariable (&gl_fogend);
4037 Cvar_RegisterVariable (&gl_skyclip);
4039 Cvar_RegisterVariable(&r_motionblur);
4040 Cvar_RegisterVariable(&r_motionblur_maxblur);
4041 Cvar_RegisterVariable(&r_motionblur_bmin);
4042 Cvar_RegisterVariable(&r_motionblur_vmin);
4043 Cvar_RegisterVariable(&r_motionblur_vmax);
4044 Cvar_RegisterVariable(&r_motionblur_vcoeff);
4045 Cvar_RegisterVariable(&r_motionblur_randomize);
4046 Cvar_RegisterVariable(&r_damageblur);
4047 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4048 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4049 Cvar_RegisterVariable(&r_equalize_entities_by);
4050 Cvar_RegisterVariable(&r_equalize_entities_to);
4051 Cvar_RegisterVariable(&r_depthfirst);
4052 Cvar_RegisterVariable(&r_useinfinitefarclip);
4053 Cvar_RegisterVariable(&r_farclip_base);
4054 Cvar_RegisterVariable(&r_farclip_world);
4055 Cvar_RegisterVariable(&r_nearclip);
4056 Cvar_RegisterVariable(&r_deformvertexes);
4057 Cvar_RegisterVariable(&r_transparent);
4058 Cvar_RegisterVariable(&r_showoverdraw);
4059 Cvar_RegisterVariable(&r_showbboxes);
4060 Cvar_RegisterVariable(&r_showsurfaces);
4061 Cvar_RegisterVariable(&r_showtris);
4062 Cvar_RegisterVariable(&r_shownormals);
4063 Cvar_RegisterVariable(&r_showlighting);
4064 Cvar_RegisterVariable(&r_showshadowvolumes);
4065 Cvar_RegisterVariable(&r_showcollisionbrushes);
4066 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4067 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4068 Cvar_RegisterVariable(&r_showdisabledepthtest);
4069 Cvar_RegisterVariable(&r_drawportals);
4070 Cvar_RegisterVariable(&r_drawentities);
4071 Cvar_RegisterVariable(&r_draw2d);
4072 Cvar_RegisterVariable(&r_drawworld);
4073 Cvar_RegisterVariable(&r_cullentities_trace);
4074 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4075 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4076 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4077 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4078 Cvar_RegisterVariable(&r_drawviewmodel);
4079 Cvar_RegisterVariable(&r_drawexteriormodel);
4080 Cvar_RegisterVariable(&r_speeds);
4081 Cvar_RegisterVariable(&r_fullbrights);
4082 Cvar_RegisterVariable(&r_wateralpha);
4083 Cvar_RegisterVariable(&r_dynamic);
4084 Cvar_RegisterVariable(&r_fakelight);
4085 Cvar_RegisterVariable(&r_fakelight_intensity);
4086 Cvar_RegisterVariable(&r_fullbright);
4087 Cvar_RegisterVariable(&r_shadows);
4088 Cvar_RegisterVariable(&r_shadows_darken);
4089 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4090 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4091 Cvar_RegisterVariable(&r_shadows_throwdistance);
4092 Cvar_RegisterVariable(&r_shadows_throwdirection);
4093 Cvar_RegisterVariable(&r_shadows_focus);
4094 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4095 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4096 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4097 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4098 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4099 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4100 Cvar_RegisterVariable(&r_fog_exp2);
4101 Cvar_RegisterVariable(&r_fog_clear);
4102 Cvar_RegisterVariable(&r_drawfog);
4103 Cvar_RegisterVariable(&r_transparentdepthmasking);
4104 Cvar_RegisterVariable(&r_texture_dds_load);
4105 Cvar_RegisterVariable(&r_texture_dds_save);
4106 Cvar_RegisterVariable(&r_texture_sRGB_2d);
4107 Cvar_RegisterVariable(&r_texture_sRGB_skin_diffuse);
4108 Cvar_RegisterVariable(&r_texture_sRGB_skin_gloss);
4109 Cvar_RegisterVariable(&r_texture_sRGB_skin_glow);
4110 Cvar_RegisterVariable(&r_texture_sRGB_skin_reflect);
4111 Cvar_RegisterVariable(&r_texture_sRGB_cubemap);
4112 Cvar_RegisterVariable(&r_texture_sRGB_skybox);
4113 Cvar_RegisterVariable(&r_textureunits);
4114 Cvar_RegisterVariable(&gl_combine);
4115 Cvar_RegisterVariable(&r_viewfbo);
4116 Cvar_RegisterVariable(&r_viewscale);
4117 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4118 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4119 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4120 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4121 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4122 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4123 Cvar_RegisterVariable(&r_glsl);
4124 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4125 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4126 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4127 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4128 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4129 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4130 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4131 Cvar_RegisterVariable(&r_glsl_postprocess);
4132 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4133 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4134 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4135 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4136 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4137 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4138 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4139 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4141 Cvar_RegisterVariable(&r_water);
4142 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4143 Cvar_RegisterVariable(&r_water_clippingplanebias);
4144 Cvar_RegisterVariable(&r_water_refractdistort);
4145 Cvar_RegisterVariable(&r_water_reflectdistort);
4146 Cvar_RegisterVariable(&r_water_scissormode);
4147 Cvar_RegisterVariable(&r_lerpsprites);
4148 Cvar_RegisterVariable(&r_lerpmodels);
4149 Cvar_RegisterVariable(&r_lerplightstyles);
4150 Cvar_RegisterVariable(&r_waterscroll);
4151 Cvar_RegisterVariable(&r_bloom);
4152 Cvar_RegisterVariable(&r_bloom_colorscale);
4153 Cvar_RegisterVariable(&r_bloom_brighten);
4154 Cvar_RegisterVariable(&r_bloom_blur);
4155 Cvar_RegisterVariable(&r_bloom_resolution);
4156 Cvar_RegisterVariable(&r_bloom_colorexponent);
4157 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4158 Cvar_RegisterVariable(&r_hdr);
4159 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4160 Cvar_RegisterVariable(&r_hdr_glowintensity);
4161 Cvar_RegisterVariable(&r_hdr_range);
4162 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4163 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4164 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4165 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4166 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4167 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4168 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4169 Cvar_RegisterVariable(&developer_texturelogging);
4170 Cvar_RegisterVariable(&gl_lightmaps);
4171 Cvar_RegisterVariable(&r_test);
4172 Cvar_RegisterVariable(&r_glsl_saturation);
4173 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4174 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4175 Cvar_RegisterVariable(&r_framedatasize);
4176 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4177 Cvar_SetValue("r_fullbrights", 0);
4178 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4180 Cvar_RegisterVariable(&r_track_sprites);
4181 Cvar_RegisterVariable(&r_track_sprites_flags);
4182 Cvar_RegisterVariable(&r_track_sprites_scalew);
4183 Cvar_RegisterVariable(&r_track_sprites_scaleh);
4184 Cvar_RegisterVariable(&r_overheadsprites_perspective);
4185 Cvar_RegisterVariable(&r_overheadsprites_pushback);
4186 Cvar_RegisterVariable(&r_overheadsprites_scalex);
4187 Cvar_RegisterVariable(&r_overheadsprites_scaley);
4190 extern void R_Textures_Init(void);
4191 extern void GL_Draw_Init(void);
4192 extern void GL_Main_Init(void);
4193 extern void R_Shadow_Init(void);
4194 extern void R_Sky_Init(void);
4195 extern void GL_Surf_Init(void);
4196 extern void R_Particles_Init(void);
4197 extern void R_Explosion_Init(void);
4198 extern void gl_backend_init(void);
4199 extern void Sbar_Init(void);
4200 extern void R_LightningBeams_Init(void);
4201 extern void Mod_RenderInit(void);
4202 extern void Font_Init(void);
4204 void Render_Init(void)
4217 R_LightningBeams_Init();
4226 extern char *ENGINE_EXTENSIONS;
4229 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4230 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4231 gl_version = (const char *)qglGetString(GL_VERSION);
4232 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4236 if (!gl_platformextensions)
4237 gl_platformextensions = "";
4239 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4240 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4241 Con_Printf("GL_VERSION: %s\n", gl_version);
4242 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4243 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4245 VID_CheckExtensions();
4247 // LordHavoc: report supported extensions
4248 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4250 // clear to black (loading plaque will be seen over this)
4251 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4254 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4258 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4260 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4263 p = r_refdef.view.frustum + i;
4268 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4272 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4276 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4280 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4284 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4288 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4292 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4296 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4304 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4308 for (i = 0;i < numplanes;i++)
4315 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4319 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4323 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4327 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4331 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4335 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4339 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4343 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4351 //==================================================================================
4353 // LordHavoc: this stores temporary data used within the same frame
4355 typedef struct r_framedata_mem_s
4357 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4358 size_t size; // how much usable space
4359 size_t current; // how much space in use
4360 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4361 size_t wantedsize; // how much space was allocated
4362 unsigned char *data; // start of real data (16byte aligned)
4366 static r_framedata_mem_t *r_framedata_mem;
4368 void R_FrameData_Reset(void)
4370 while (r_framedata_mem)
4372 r_framedata_mem_t *next = r_framedata_mem->purge;
4373 Mem_Free(r_framedata_mem);
4374 r_framedata_mem = next;
4378 void R_FrameData_Resize(void)
4381 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4382 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4383 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4385 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4386 newmem->wantedsize = wantedsize;
4387 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4388 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4389 newmem->current = 0;
4391 newmem->purge = r_framedata_mem;
4392 r_framedata_mem = newmem;
4396 void R_FrameData_NewFrame(void)
4398 R_FrameData_Resize();
4399 if (!r_framedata_mem)
4401 // if we ran out of space on the last frame, free the old memory now
4402 while (r_framedata_mem->purge)
4404 // repeatedly remove the second item in the list, leaving only head
4405 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4406 Mem_Free(r_framedata_mem->purge);
4407 r_framedata_mem->purge = next;
4409 // reset the current mem pointer
4410 r_framedata_mem->current = 0;
4411 r_framedata_mem->mark = 0;
4414 void *R_FrameData_Alloc(size_t size)
4418 // align to 16 byte boundary - the data pointer is already aligned, so we
4419 // only need to ensure the size of every allocation is also aligned
4420 size = (size + 15) & ~15;
4422 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4424 // emergency - we ran out of space, allocate more memory
4425 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4426 R_FrameData_Resize();
4429 data = r_framedata_mem->data + r_framedata_mem->current;
4430 r_framedata_mem->current += size;
4432 // count the usage for stats
4433 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4434 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4436 return (void *)data;
4439 void *R_FrameData_Store(size_t size, void *data)
4441 void *d = R_FrameData_Alloc(size);
4443 memcpy(d, data, size);
4447 void R_FrameData_SetMark(void)
4449 if (!r_framedata_mem)
4451 r_framedata_mem->mark = r_framedata_mem->current;
4454 void R_FrameData_ReturnToMark(void)
4456 if (!r_framedata_mem)
4458 r_framedata_mem->current = r_framedata_mem->mark;
4461 //==================================================================================
4463 // LordHavoc: animcache originally written by Echon, rewritten since then
4466 * Animation cache prevents re-generating mesh data for an animated model
4467 * multiple times in one frame for lighting, shadowing, reflections, etc.
4470 void R_AnimCache_Free(void)
4474 void R_AnimCache_ClearCache(void)
4477 entity_render_t *ent;
4479 for (i = 0;i < r_refdef.scene.numentities;i++)
4481 ent = r_refdef.scene.entities[i];
4482 ent->animcache_vertex3f = NULL;
4483 ent->animcache_normal3f = NULL;
4484 ent->animcache_svector3f = NULL;
4485 ent->animcache_tvector3f = NULL;
4486 ent->animcache_vertexmesh = NULL;
4487 ent->animcache_vertex3fbuffer = NULL;
4488 ent->animcache_vertexmeshbuffer = NULL;
4492 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4496 // check if we need the meshbuffers
4497 if (!vid.useinterleavedarrays)
4500 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4501 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4502 // TODO: upload vertex3f buffer?
4503 if (ent->animcache_vertexmesh)
4505 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4506 for (i = 0;i < numvertices;i++)
4507 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4508 if (ent->animcache_svector3f)
4509 for (i = 0;i < numvertices;i++)
4510 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4511 if (ent->animcache_tvector3f)
4512 for (i = 0;i < numvertices;i++)
4513 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4514 if (ent->animcache_normal3f)
4515 for (i = 0;i < numvertices;i++)
4516 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4517 // TODO: upload vertexmeshbuffer?
4521 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4523 dp_model_t *model = ent->model;
4525 // see if it's already cached this frame
4526 if (ent->animcache_vertex3f)
4528 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4529 if (wantnormals || wanttangents)
4531 if (ent->animcache_normal3f)
4532 wantnormals = false;
4533 if (ent->animcache_svector3f)
4534 wanttangents = false;
4535 if (wantnormals || wanttangents)
4537 numvertices = model->surfmesh.num_vertices;
4539 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4542 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4543 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4545 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4546 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4552 // see if this ent is worth caching
4553 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4555 // get some memory for this entity and generate mesh data
4556 numvertices = model->surfmesh.num_vertices;
4557 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4559 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4562 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4563 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4565 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4566 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4571 void R_AnimCache_CacheVisibleEntities(void)
4574 qboolean wantnormals = true;
4575 qboolean wanttangents = !r_showsurfaces.integer;
4577 switch(vid.renderpath)
4579 case RENDERPATH_GL20:
4580 case RENDERPATH_D3D9:
4581 case RENDERPATH_D3D10:
4582 case RENDERPATH_D3D11:
4583 case RENDERPATH_GLES2:
4585 case RENDERPATH_GL11:
4586 case RENDERPATH_GL13:
4587 case RENDERPATH_GLES1:
4588 wanttangents = false;
4590 case RENDERPATH_SOFT:
4594 if (r_shownormals.integer)
4595 wanttangents = wantnormals = true;
4597 // TODO: thread this
4598 // NOTE: R_PrepareRTLights() also caches entities
4600 for (i = 0;i < r_refdef.scene.numentities;i++)
4601 if (r_refdef.viewcache.entityvisible[i])
4602 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4605 //==================================================================================
4607 static void R_View_UpdateEntityLighting (void)
4610 entity_render_t *ent;
4611 vec3_t tempdiffusenormal, avg;
4612 vec_t f, fa, fd, fdd;
4613 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4615 for (i = 0;i < r_refdef.scene.numentities;i++)
4617 ent = r_refdef.scene.entities[i];
4619 // skip unseen models
4620 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4624 if (ent->model && ent->model->brush.num_leafs)
4626 // TODO: use modellight for r_ambient settings on world?
4627 VectorSet(ent->modellight_ambient, 0, 0, 0);
4628 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4629 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4633 // fetch the lighting from the worldmodel data
4634 VectorClear(ent->modellight_ambient);
4635 VectorClear(ent->modellight_diffuse);
4636 VectorClear(tempdiffusenormal);
4637 if (ent->flags & RENDER_LIGHT)
4640 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4642 // complete lightning for lit sprites
4643 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4644 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4646 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4647 org[2] = org[2] + r_overheadsprites_pushback.value;
4648 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4651 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4653 if(ent->flags & RENDER_EQUALIZE)
4655 // first fix up ambient lighting...
4656 if(r_equalize_entities_minambient.value > 0)
4658 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4661 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4662 if(fa < r_equalize_entities_minambient.value * fd)
4665 // fa'/fd' = minambient
4666 // fa'+0.25*fd' = fa+0.25*fd
4668 // fa' = fd' * minambient
4669 // fd'*(0.25+minambient) = fa+0.25*fd
4671 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4672 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4674 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4675 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
4676 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4677 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4682 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4684 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4685 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4689 // adjust brightness and saturation to target
4690 avg[0] = avg[1] = avg[2] = fa / f;
4691 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4692 avg[0] = avg[1] = avg[2] = fd / f;
4693 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4699 VectorSet(ent->modellight_ambient, 1, 1, 1);
4701 // move the light direction into modelspace coordinates for lighting code
4702 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4703 if(VectorLength2(ent->modellight_lightdir) == 0)
4704 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4705 VectorNormalize(ent->modellight_lightdir);
4709 #define MAX_LINEOFSIGHTTRACES 64
4711 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4714 vec3_t boxmins, boxmaxs;
4717 dp_model_t *model = r_refdef.scene.worldmodel;
4719 if (!model || !model->brush.TraceLineOfSight)
4722 // expand the box a little
4723 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4724 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4725 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4726 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4727 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4728 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4730 // return true if eye is inside enlarged box
4731 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4735 VectorCopy(eye, start);
4736 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4737 if (model->brush.TraceLineOfSight(model, start, end))
4740 // try various random positions
4741 for (i = 0;i < numsamples;i++)
4743 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4744 if (model->brush.TraceLineOfSight(model, start, end))
4752 static void R_View_UpdateEntityVisible (void)
4757 entity_render_t *ent;
4759 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4760 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4761 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
4762 : RENDER_EXTERIORMODEL;
4763 if (!r_drawviewmodel.integer)
4764 renderimask |= RENDER_VIEWMODEL;
4765 if (!r_drawexteriormodel.integer)
4766 renderimask |= RENDER_EXTERIORMODEL;
4767 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4769 // worldmodel can check visibility
4770 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4771 for (i = 0;i < r_refdef.scene.numentities;i++)
4773 ent = r_refdef.scene.entities[i];
4774 if (!(ent->flags & renderimask))
4775 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)))
4776 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))
4777 r_refdef.viewcache.entityvisible[i] = true;
4782 // no worldmodel or it can't check visibility
4783 for (i = 0;i < r_refdef.scene.numentities;i++)
4785 ent = r_refdef.scene.entities[i];
4786 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));
4789 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4790 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4792 for (i = 0;i < r_refdef.scene.numentities;i++)
4794 if (!r_refdef.viewcache.entityvisible[i])
4796 ent = r_refdef.scene.entities[i];
4797 if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4799 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4801 continue; // temp entities do pvs only
4802 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4803 ent->last_trace_visibility = realtime;
4804 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4805 r_refdef.viewcache.entityvisible[i] = 0;
4811 /// only used if skyrendermasked, and normally returns false
4812 int R_DrawBrushModelsSky (void)
4815 entity_render_t *ent;
4818 for (i = 0;i < r_refdef.scene.numentities;i++)
4820 if (!r_refdef.viewcache.entityvisible[i])
4822 ent = r_refdef.scene.entities[i];
4823 if (!ent->model || !ent->model->DrawSky)
4825 ent->model->DrawSky(ent);
4831 static void R_DrawNoModel(entity_render_t *ent);
4832 static void R_DrawModels(void)
4835 entity_render_t *ent;
4837 for (i = 0;i < r_refdef.scene.numentities;i++)
4839 if (!r_refdef.viewcache.entityvisible[i])
4841 ent = r_refdef.scene.entities[i];
4842 r_refdef.stats.entities++;
4843 if (ent->model && ent->model->Draw != NULL)
4844 ent->model->Draw(ent);
4850 static void R_DrawModelsDepth(void)
4853 entity_render_t *ent;
4855 for (i = 0;i < r_refdef.scene.numentities;i++)
4857 if (!r_refdef.viewcache.entityvisible[i])
4859 ent = r_refdef.scene.entities[i];
4860 if (ent->model && ent->model->DrawDepth != NULL)
4861 ent->model->DrawDepth(ent);
4865 static void R_DrawModelsDebug(void)
4868 entity_render_t *ent;
4870 for (i = 0;i < r_refdef.scene.numentities;i++)
4872 if (!r_refdef.viewcache.entityvisible[i])
4874 ent = r_refdef.scene.entities[i];
4875 if (ent->model && ent->model->DrawDebug != NULL)
4876 ent->model->DrawDebug(ent);
4880 static void R_DrawModelsAddWaterPlanes(void)
4883 entity_render_t *ent;
4885 for (i = 0;i < r_refdef.scene.numentities;i++)
4887 if (!r_refdef.viewcache.entityvisible[i])
4889 ent = r_refdef.scene.entities[i];
4890 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4891 ent->model->DrawAddWaterPlanes(ent);
4895 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4897 if (r_hdr_irisadaptation.integer)
4901 vec3_t diffusenormal;
4906 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4907 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4908 brightness = max(0.0000001f, brightness);
4909 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4910 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4911 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4912 current = r_hdr_irisadaptation_value.value;
4914 current = min(current + adjust, goal);
4915 else if (current > goal)
4916 current = max(current - adjust, goal);
4917 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4918 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4920 else if (r_hdr_irisadaptation_value.value != 1.0f)
4921 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4924 static void R_View_SetFrustum(const int *scissor)
4927 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4928 vec3_t forward, left, up, origin, v;
4932 // flipped x coordinates (because x points left here)
4933 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4934 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4936 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4937 switch(vid.renderpath)
4939 case RENDERPATH_D3D9:
4940 case RENDERPATH_D3D10:
4941 case RENDERPATH_D3D11:
4942 // non-flipped y coordinates
4943 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4944 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4946 case RENDERPATH_SOFT:
4947 case RENDERPATH_GL11:
4948 case RENDERPATH_GL13:
4949 case RENDERPATH_GL20:
4950 case RENDERPATH_GLES1:
4951 case RENDERPATH_GLES2:
4952 // non-flipped y coordinates
4953 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4954 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4959 // we can't trust r_refdef.view.forward and friends in reflected scenes
4960 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4963 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4964 r_refdef.view.frustum[0].normal[1] = 0 - 0;
4965 r_refdef.view.frustum[0].normal[2] = -1 - 0;
4966 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4967 r_refdef.view.frustum[1].normal[1] = 0 + 0;
4968 r_refdef.view.frustum[1].normal[2] = -1 + 0;
4969 r_refdef.view.frustum[2].normal[0] = 0 - 0;
4970 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4971 r_refdef.view.frustum[2].normal[2] = -1 - 0;
4972 r_refdef.view.frustum[3].normal[0] = 0 + 0;
4973 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4974 r_refdef.view.frustum[3].normal[2] = -1 + 0;
4978 zNear = r_refdef.nearclip;
4979 nudge = 1.0 - 1.0 / (1<<23);
4980 r_refdef.view.frustum[4].normal[0] = 0 - 0;
4981 r_refdef.view.frustum[4].normal[1] = 0 - 0;
4982 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4983 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4984 r_refdef.view.frustum[5].normal[0] = 0 + 0;
4985 r_refdef.view.frustum[5].normal[1] = 0 + 0;
4986 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4987 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4993 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4994 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4995 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4996 r_refdef.view.frustum[0].dist = m[15] - m[12];
4998 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4999 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5000 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5001 r_refdef.view.frustum[1].dist = m[15] + m[12];
5003 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5004 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5005 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5006 r_refdef.view.frustum[2].dist = m[15] - m[13];
5008 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5009 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5010 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5011 r_refdef.view.frustum[3].dist = m[15] + m[13];
5013 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5014 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5015 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5016 r_refdef.view.frustum[4].dist = m[15] - m[14];
5018 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5019 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5020 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5021 r_refdef.view.frustum[5].dist = m[15] + m[14];
5024 if (r_refdef.view.useperspective)
5026 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5027 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]);
5028 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]);
5029 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]);
5030 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]);
5032 // then the normals from the corners relative to origin
5033 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5034 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5035 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5036 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5038 // in a NORMAL view, forward cross left == up
5039 // in a REFLECTED view, forward cross left == down
5040 // so our cross products above need to be adjusted for a left handed coordinate system
5041 CrossProduct(forward, left, v);
5042 if(DotProduct(v, up) < 0)
5044 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5045 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5046 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5047 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5050 // Leaving those out was a mistake, those were in the old code, and they
5051 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5052 // I couldn't reproduce it after adding those normalizations. --blub
5053 VectorNormalize(r_refdef.view.frustum[0].normal);
5054 VectorNormalize(r_refdef.view.frustum[1].normal);
5055 VectorNormalize(r_refdef.view.frustum[2].normal);
5056 VectorNormalize(r_refdef.view.frustum[3].normal);
5058 // make the corners absolute
5059 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5060 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5061 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5062 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5065 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5067 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5068 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5069 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5070 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5071 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5075 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5076 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5077 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5078 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5079 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5080 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5081 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5082 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5083 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5084 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5086 r_refdef.view.numfrustumplanes = 5;
5088 if (r_refdef.view.useclipplane)
5090 r_refdef.view.numfrustumplanes = 6;
5091 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5094 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5095 PlaneClassify(r_refdef.view.frustum + i);
5097 // LordHavoc: note to all quake engine coders, Quake had a special case
5098 // for 90 degrees which assumed a square view (wrong), so I removed it,
5099 // Quake2 has it disabled as well.
5101 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5102 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5103 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5104 //PlaneClassify(&frustum[0]);
5106 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5107 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5108 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5109 //PlaneClassify(&frustum[1]);
5111 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5112 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5113 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5114 //PlaneClassify(&frustum[2]);
5116 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5117 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5118 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5119 //PlaneClassify(&frustum[3]);
5122 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5123 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5124 //PlaneClassify(&frustum[4]);
5127 void R_View_UpdateWithScissor(const int *myscissor)
5129 R_Main_ResizeViewCache();
5130 R_View_SetFrustum(myscissor);
5131 R_View_WorldVisibility(r_refdef.view.useclipplane);
5132 R_View_UpdateEntityVisible();
5133 R_View_UpdateEntityLighting();
5136 void R_View_Update(void)
5138 R_Main_ResizeViewCache();
5139 R_View_SetFrustum(NULL);
5140 R_View_WorldVisibility(r_refdef.view.useclipplane);
5141 R_View_UpdateEntityVisible();
5142 R_View_UpdateEntityLighting();
5145 float viewscalefpsadjusted = 1.0f;
5147 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5149 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5150 scale = bound(0.03125f, scale, 1.0f);
5151 *outwidth = (int)ceil(width * scale);
5152 *outheight = (int)ceil(height * scale);
5155 void R_Mesh_SetMainRenderTargets(void)
5157 if (r_bloomstate.fbo_framebuffer)
5158 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5160 R_Mesh_ResetRenderTargets();
5163 void R_SetupView(qboolean allowwaterclippingplane)
5165 const float *customclipplane = NULL;
5167 int scaledwidth, scaledheight;
5168 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5170 // LordHavoc: couldn't figure out how to make this approach the
5171 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5172 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5173 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5174 dist = r_refdef.view.clipplane.dist;
5175 plane[0] = r_refdef.view.clipplane.normal[0];
5176 plane[1] = r_refdef.view.clipplane.normal[1];
5177 plane[2] = r_refdef.view.clipplane.normal[2];
5179 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5182 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5183 if (!r_refdef.view.useperspective)
5184 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);
5185 else if (vid.stencil && r_useinfinitefarclip.integer)
5186 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);
5188 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);
5189 R_Mesh_SetMainRenderTargets();
5190 R_SetViewport(&r_refdef.view.viewport);
5191 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5193 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5194 float screenplane[4];
5195 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5196 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5197 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5198 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5199 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5203 void R_EntityMatrix(const matrix4x4_t *matrix)
5205 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5207 gl_modelmatrixchanged = false;
5208 gl_modelmatrix = *matrix;
5209 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5210 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5211 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5212 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5214 switch(vid.renderpath)
5216 case RENDERPATH_D3D9:
5218 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5219 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5222 case RENDERPATH_D3D10:
5223 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5225 case RENDERPATH_D3D11:
5226 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5228 case RENDERPATH_GL11:
5229 case RENDERPATH_GL13:
5230 case RENDERPATH_GLES1:
5231 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5233 case RENDERPATH_SOFT:
5234 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5235 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5237 case RENDERPATH_GL20:
5238 case RENDERPATH_GLES2:
5239 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5240 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5246 void R_ResetViewRendering2D(void)
5248 r_viewport_t viewport;
5251 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5252 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);
5253 R_Mesh_ResetRenderTargets();
5254 R_SetViewport(&viewport);
5255 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5256 GL_Color(1, 1, 1, 1);
5257 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5258 GL_BlendFunc(GL_ONE, GL_ZERO);
5259 GL_ScissorTest(false);
5260 GL_DepthMask(false);
5261 GL_DepthRange(0, 1);
5262 GL_DepthTest(false);
5263 GL_DepthFunc(GL_LEQUAL);
5264 R_EntityMatrix(&identitymatrix);
5265 R_Mesh_ResetTextureState();
5266 GL_PolygonOffset(0, 0);
5267 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5268 switch(vid.renderpath)
5270 case RENDERPATH_GL11:
5271 case RENDERPATH_GL13:
5272 case RENDERPATH_GL20:
5273 case RENDERPATH_GLES1:
5274 case RENDERPATH_GLES2:
5275 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5277 case RENDERPATH_D3D9:
5278 case RENDERPATH_D3D10:
5279 case RENDERPATH_D3D11:
5280 case RENDERPATH_SOFT:
5283 GL_CullFace(GL_NONE);
5286 void R_ResetViewRendering3D(void)
5291 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5292 GL_Color(1, 1, 1, 1);
5293 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5294 GL_BlendFunc(GL_ONE, GL_ZERO);
5295 GL_ScissorTest(true);
5297 GL_DepthRange(0, 1);
5299 GL_DepthFunc(GL_LEQUAL);
5300 R_EntityMatrix(&identitymatrix);
5301 R_Mesh_ResetTextureState();
5302 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5303 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5304 switch(vid.renderpath)
5306 case RENDERPATH_GL11:
5307 case RENDERPATH_GL13:
5308 case RENDERPATH_GL20:
5309 case RENDERPATH_GLES1:
5310 case RENDERPATH_GLES2:
5311 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5313 case RENDERPATH_D3D9:
5314 case RENDERPATH_D3D10:
5315 case RENDERPATH_D3D11:
5316 case RENDERPATH_SOFT:
5319 GL_CullFace(r_refdef.view.cullface_back);
5324 R_RenderView_UpdateViewVectors
5327 static void R_RenderView_UpdateViewVectors(void)
5329 // break apart the view matrix into vectors for various purposes
5330 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5331 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5332 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5333 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5334 // make an inverted copy of the view matrix for tracking sprites
5335 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5338 void R_RenderScene(void);
5339 void R_RenderWaterPlanes(void);
5341 static void R_Water_StartFrame(void)
5344 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5345 r_waterstate_waterplane_t *p;
5347 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5350 switch(vid.renderpath)
5352 case RENDERPATH_GL20:
5353 case RENDERPATH_D3D9:
5354 case RENDERPATH_D3D10:
5355 case RENDERPATH_D3D11:
5356 case RENDERPATH_SOFT:
5357 case RENDERPATH_GLES2:
5359 case RENDERPATH_GL11:
5360 case RENDERPATH_GL13:
5361 case RENDERPATH_GLES1:
5365 // set waterwidth and waterheight to the water resolution that will be
5366 // used (often less than the screen resolution for faster rendering)
5367 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5368 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5370 // calculate desired texture sizes
5371 // can't use water if the card does not support the texture size
5372 if (!r_water.integer || r_showsurfaces.integer)
5373 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5374 else if (vid.support.arb_texture_non_power_of_two)
5376 texturewidth = waterwidth;
5377 textureheight = waterheight;
5378 camerawidth = waterwidth;
5379 cameraheight = waterheight;
5383 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5384 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5385 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5386 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5389 // allocate textures as needed
5390 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5392 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5393 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5395 if (p->texture_refraction)
5396 R_FreeTexture(p->texture_refraction);
5397 p->texture_refraction = NULL;
5398 if (p->texture_reflection)
5399 R_FreeTexture(p->texture_reflection);
5400 p->texture_reflection = NULL;
5401 if (p->texture_camera)
5402 R_FreeTexture(p->texture_camera);
5403 p->texture_camera = NULL;
5405 memset(&r_waterstate, 0, sizeof(r_waterstate));
5406 r_waterstate.texturewidth = texturewidth;
5407 r_waterstate.textureheight = textureheight;
5408 r_waterstate.camerawidth = camerawidth;
5409 r_waterstate.cameraheight = cameraheight;
5412 if (r_waterstate.texturewidth)
5414 r_waterstate.enabled = true;
5416 // when doing a reduced render (HDR) we want to use a smaller area
5417 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5418 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5420 // set up variables that will be used in shader setup
5421 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5422 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5423 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5424 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5427 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5428 r_waterstate.numwaterplanes = 0;
5431 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5433 int triangleindex, planeindex;
5439 r_waterstate_waterplane_t *p;
5440 texture_t *t = R_GetCurrentTexture(surface->texture);
5442 // just use the first triangle with a valid normal for any decisions
5443 VectorClear(normal);
5444 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5446 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5447 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5448 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5449 TriangleNormal(vert[0], vert[1], vert[2], normal);
5450 if (VectorLength2(normal) >= 0.001)
5454 VectorCopy(normal, plane.normal);
5455 VectorNormalize(plane.normal);
5456 plane.dist = DotProduct(vert[0], plane.normal);
5457 PlaneClassify(&plane);
5458 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5460 // skip backfaces (except if nocullface is set)
5461 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5463 VectorNegate(plane.normal, plane.normal);
5465 PlaneClassify(&plane);
5469 // find a matching plane if there is one
5470 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5471 if(p->camera_entity == t->camera_entity)
5472 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5474 if (planeindex >= r_waterstate.maxwaterplanes)
5475 return; // nothing we can do, out of planes
5477 // if this triangle does not fit any known plane rendered this frame, add one
5478 if (planeindex >= r_waterstate.numwaterplanes)
5480 // store the new plane
5481 r_waterstate.numwaterplanes++;
5483 // clear materialflags and pvs
5484 p->materialflags = 0;
5485 p->pvsvalid = false;
5486 p->camera_entity = t->camera_entity;
5487 VectorCopy(surface->mins, p->mins);
5488 VectorCopy(surface->maxs, p->maxs);
5493 p->mins[0] = min(p->mins[0], surface->mins[0]);
5494 p->mins[1] = min(p->mins[1], surface->mins[1]);
5495 p->mins[2] = min(p->mins[2], surface->mins[2]);
5496 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5497 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5498 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5500 // merge this surface's materialflags into the waterplane
5501 p->materialflags |= t->currentmaterialflags;
5502 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5504 // merge this surface's PVS into the waterplane
5505 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5506 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5507 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5509 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5515 static void R_Water_ProcessPlanes(void)
5518 r_refdef_view_t originalview;
5519 r_refdef_view_t myview;
5521 r_waterstate_waterplane_t *p;
5524 originalview = r_refdef.view;
5526 // make sure enough textures are allocated
5527 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5529 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5531 if (!p->texture_refraction)
5532 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);
5533 if (!p->texture_refraction)
5536 else if (p->materialflags & MATERIALFLAG_CAMERA)
5538 if (!p->texture_camera)
5539 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);
5540 if (!p->texture_camera)
5544 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5546 if (!p->texture_reflection)
5547 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);
5548 if (!p->texture_reflection)
5554 r_refdef.view = originalview;
5555 r_refdef.view.showdebug = false;
5556 r_refdef.view.width = r_waterstate.waterwidth;
5557 r_refdef.view.height = r_waterstate.waterheight;
5558 r_refdef.view.useclipplane = true;
5559 myview = r_refdef.view;
5560 r_waterstate.renderingscene = true;
5561 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5563 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
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 // render reflected scene and copy into texture
5574 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5575 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5576 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5577 r_refdef.view.clipplane = p->plane;
5579 // reverse the cullface settings for this render
5580 r_refdef.view.cullface_front = GL_FRONT;
5581 r_refdef.view.cullface_back = GL_BACK;
5582 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5584 r_refdef.view.usecustompvs = true;
5586 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5588 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5591 R_ResetViewRendering3D();
5592 R_ClearScreen(r_refdef.fogenabled);
5593 if(r_water_scissormode.integer & 2)
5594 R_View_UpdateWithScissor(myscissor);
5597 if(r_water_scissormode.integer & 1)
5598 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5601 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);
5604 // render the normal view scene and copy into texture
5605 // (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)
5606 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5608 r_refdef.view = myview;
5609 if(r_water_scissormode.integer)
5612 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5613 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5616 r_waterstate.renderingrefraction = true;
5618 r_refdef.view.clipplane = p->plane;
5619 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5620 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5622 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5624 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5625 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5626 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5627 R_RenderView_UpdateViewVectors();
5628 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5630 r_refdef.view.usecustompvs = true;
5631 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);
5635 PlaneClassify(&r_refdef.view.clipplane);
5637 R_ResetViewRendering3D();
5638 R_ClearScreen(r_refdef.fogenabled);
5639 if(r_water_scissormode.integer & 2)
5640 R_View_UpdateWithScissor(myscissor);
5643 if(r_water_scissormode.integer & 1)
5644 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5647 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);
5648 r_waterstate.renderingrefraction = false;
5650 else if (p->materialflags & MATERIALFLAG_CAMERA)
5652 r_refdef.view = myview;
5654 r_refdef.view.clipplane = p->plane;
5655 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5656 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5658 r_refdef.view.width = r_waterstate.camerawidth;
5659 r_refdef.view.height = r_waterstate.cameraheight;
5660 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5661 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5663 if(p->camera_entity)
5665 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5666 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5669 // note: all of the view is used for displaying... so
5670 // there is no use in scissoring
5672 // reverse the cullface settings for this render
5673 r_refdef.view.cullface_front = GL_FRONT;
5674 r_refdef.view.cullface_back = GL_BACK;
5675 // also reverse the view matrix
5676 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
5677 R_RenderView_UpdateViewVectors();
5678 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5680 r_refdef.view.usecustompvs = true;
5681 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);
5684 // camera needs no clipplane
5685 r_refdef.view.useclipplane = false;
5687 PlaneClassify(&r_refdef.view.clipplane);
5689 R_ResetViewRendering3D();
5690 R_ClearScreen(r_refdef.fogenabled);
5694 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);
5695 r_waterstate.renderingrefraction = false;
5699 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5700 r_waterstate.renderingscene = false;
5701 r_refdef.view = originalview;
5702 R_ResetViewRendering3D();
5703 R_ClearScreen(r_refdef.fogenabled);
5707 r_refdef.view = originalview;
5708 r_waterstate.renderingscene = false;
5709 Cvar_SetValueQuick(&r_water, 0);
5710 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5714 void R_Bloom_StartFrame(void)
5716 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5717 int viewwidth, viewheight;
5720 if (r_viewscale_fpsscaling.integer)
5722 double actualframetime;
5723 double targetframetime;
5725 actualframetime = r_refdef.lastdrawscreentime;
5726 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5727 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5728 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5729 if (r_viewscale_fpsscaling_stepsize.value > 0)
5730 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5731 viewscalefpsadjusted += adjust;
5732 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5735 viewscalefpsadjusted = 1.0f;
5737 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5739 switch(vid.renderpath)
5741 case RENDERPATH_GL20:
5742 case RENDERPATH_D3D9:
5743 case RENDERPATH_D3D10:
5744 case RENDERPATH_D3D11:
5745 case RENDERPATH_SOFT:
5746 case RENDERPATH_GLES2:
5748 case RENDERPATH_GL11:
5749 case RENDERPATH_GL13:
5750 case RENDERPATH_GLES1:
5754 // set bloomwidth and bloomheight to the bloom resolution that will be
5755 // used (often less than the screen resolution for faster rendering)
5756 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5757 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5758 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5759 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5760 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5762 // calculate desired texture sizes
5763 if (vid.support.arb_texture_non_power_of_two)
5765 screentexturewidth = vid.width;
5766 screentextureheight = vid.height;
5767 bloomtexturewidth = r_bloomstate.bloomwidth;
5768 bloomtextureheight = r_bloomstate.bloomheight;
5772 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
5773 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
5774 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
5775 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
5778 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))
5780 Cvar_SetValueQuick(&r_hdr, 0);
5781 Cvar_SetValueQuick(&r_bloom, 0);
5782 Cvar_SetValueQuick(&r_motionblur, 0);
5783 Cvar_SetValueQuick(&r_damageblur, 0);
5786 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)
5787 screentexturewidth = screentextureheight = 0;
5788 if (!r_hdr.integer && !r_bloom.integer)
5789 bloomtexturewidth = bloomtextureheight = 0;
5791 textype = TEXTYPE_COLORBUFFER;
5792 switch (vid.renderpath)
5794 case RENDERPATH_GL20:
5795 case RENDERPATH_GLES2:
5796 if (vid.support.ext_framebuffer_object)
5798 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5799 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5802 case RENDERPATH_GL11:
5803 case RENDERPATH_GL13:
5804 case RENDERPATH_GLES1:
5805 case RENDERPATH_D3D9:
5806 case RENDERPATH_D3D10:
5807 case RENDERPATH_D3D11:
5808 case RENDERPATH_SOFT:
5812 // allocate textures as needed
5813 if (r_bloomstate.screentexturewidth != screentexturewidth
5814 || r_bloomstate.screentextureheight != screentextureheight
5815 || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5816 || r_bloomstate.bloomtextureheight != bloomtextureheight
5817 || r_bloomstate.texturetype != textype
5818 || r_bloomstate.viewfbo != r_viewfbo.integer)
5820 if (r_bloomstate.texture_bloom)
5821 R_FreeTexture(r_bloomstate.texture_bloom);
5822 r_bloomstate.texture_bloom = NULL;
5823 if (r_bloomstate.texture_screen)
5824 R_FreeTexture(r_bloomstate.texture_screen);
5825 r_bloomstate.texture_screen = NULL;
5826 if (r_bloomstate.fbo_framebuffer)
5827 R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5828 r_bloomstate.fbo_framebuffer = 0;
5829 if (r_bloomstate.texture_framebuffercolor)
5830 R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5831 r_bloomstate.texture_framebuffercolor = NULL;
5832 if (r_bloomstate.texture_framebufferdepth)
5833 R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5834 r_bloomstate.texture_framebufferdepth = NULL;
5835 r_bloomstate.screentexturewidth = screentexturewidth;
5836 r_bloomstate.screentextureheight = screentextureheight;
5837 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5838 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);
5839 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5841 // FIXME: choose depth bits based on a cvar
5842 r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5843 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);
5844 r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5845 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5846 // render depth into one texture and normalmap into the other
5850 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5851 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5852 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
5853 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
5854 Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
5857 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5858 r_bloomstate.bloomtextureheight = bloomtextureheight;
5859 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5860 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);
5861 r_bloomstate.viewfbo = r_viewfbo.integer;
5862 r_bloomstate.texturetype = textype;
5865 // when doing a reduced render (HDR) we want to use a smaller area
5866 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5867 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5868 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5869 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5870 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5872 // set up a texcoord array for the full resolution screen image
5873 // (we have to keep this around to copy back during final render)
5874 r_bloomstate.screentexcoord2f[0] = 0;
5875 r_bloomstate.screentexcoord2f[1] = (float)viewheight / (float)r_bloomstate.screentextureheight;
5876 r_bloomstate.screentexcoord2f[2] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
5877 r_bloomstate.screentexcoord2f[3] = (float)viewheight / (float)r_bloomstate.screentextureheight;
5878 r_bloomstate.screentexcoord2f[4] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
5879 r_bloomstate.screentexcoord2f[5] = 0;
5880 r_bloomstate.screentexcoord2f[6] = 0;
5881 r_bloomstate.screentexcoord2f[7] = 0;
5883 // set up a texcoord array for the reduced resolution bloom image
5884 // (which will be additive blended over the screen image)
5885 r_bloomstate.bloomtexcoord2f[0] = 0;
5886 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5887 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5888 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5889 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5890 r_bloomstate.bloomtexcoord2f[5] = 0;
5891 r_bloomstate.bloomtexcoord2f[6] = 0;
5892 r_bloomstate.bloomtexcoord2f[7] = 0;
5894 switch(vid.renderpath)
5896 case RENDERPATH_GL11:
5897 case RENDERPATH_GL13:
5898 case RENDERPATH_GL20:
5899 case RENDERPATH_SOFT:
5900 case RENDERPATH_GLES1:
5901 case RENDERPATH_GLES2:
5903 case RENDERPATH_D3D9:
5904 case RENDERPATH_D3D10:
5905 case RENDERPATH_D3D11:
5908 for (i = 0;i < 4;i++)
5910 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5911 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5912 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5913 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5919 if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
5921 r_bloomstate.enabled = true;
5922 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
5925 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);
5927 if (r_bloomstate.fbo_framebuffer)
5928 r_refdef.view.clear = true;
5931 void R_Bloom_CopyBloomTexture(float colorscale)
5933 r_refdef.stats.bloom++;
5935 // scale down screen texture to the bloom texture size
5937 R_Mesh_SetMainRenderTargets();
5938 R_SetViewport(&r_bloomstate.viewport);
5939 GL_BlendFunc(GL_ONE, GL_ZERO);
5940 GL_Color(colorscale, colorscale, colorscale, 1);
5941 // 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...
5942 switch(vid.renderpath)
5944 case RENDERPATH_GL11:
5945 case RENDERPATH_GL13:
5946 case RENDERPATH_GL20:
5947 case RENDERPATH_GLES1:
5948 case RENDERPATH_GLES2:
5949 case RENDERPATH_SOFT:
5950 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5952 case RENDERPATH_D3D9:
5953 case RENDERPATH_D3D10:
5954 case RENDERPATH_D3D11:
5955 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5958 // TODO: do boxfilter scale-down in shader?
5959 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5960 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5961 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5963 // we now have a bloom image in the framebuffer
5964 // copy it into the bloom image texture for later processing
5965 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);
5966 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5969 void R_Bloom_CopyHDRTexture(void)
5971 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);
5972 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5975 void R_Bloom_MakeTexture(void)
5978 float xoffset, yoffset, r, brighten;
5980 r_refdef.stats.bloom++;
5982 R_ResetViewRendering2D();
5984 // we have a bloom image in the framebuffer
5986 R_SetViewport(&r_bloomstate.viewport);
5988 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5991 r = bound(0, r_bloom_colorexponent.value / x, 1);
5992 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5994 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5995 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5996 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5997 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5999 // copy the vertically blurred bloom view to a texture
6000 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);
6001 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6004 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6005 brighten = r_bloom_brighten.value;
6006 if (r_bloomstate.hdr)
6007 brighten *= r_hdr_range.value;
6008 brighten = sqrt(brighten);
6010 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6011 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
6013 for (dir = 0;dir < 2;dir++)
6015 // blend on at multiple vertical offsets to achieve a vertical blur
6016 // TODO: do offset blends using GLSL
6017 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6018 GL_BlendFunc(GL_ONE, GL_ZERO);
6019 for (x = -range;x <= range;x++)
6021 if (!dir){xoffset = 0;yoffset = x;}
6022 else {xoffset = x;yoffset = 0;}
6023 xoffset /= (float)r_bloomstate.bloomtexturewidth;
6024 yoffset /= (float)r_bloomstate.bloomtextureheight;
6025 // compute a texcoord array with the specified x and y offset
6026 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6027 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6028 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6029 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6030 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6031 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6032 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6033 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6034 // this r value looks like a 'dot' particle, fading sharply to
6035 // black at the edges
6036 // (probably not realistic but looks good enough)
6037 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6038 //r = brighten/(range*2+1);
6039 r = brighten / (range * 2 + 1);
6041 r *= (1 - x*x/(float)(range*range));
6042 GL_Color(r, r, r, 1);
6043 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6044 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6045 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6046 GL_BlendFunc(GL_ONE, GL_ONE);
6049 // copy the vertically blurred bloom view to a texture
6050 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);
6051 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6055 void R_HDR_RenderBloomTexture(void)
6057 int oldwidth, oldheight;
6058 float oldcolorscale;
6059 qboolean oldwaterstate;
6061 oldwaterstate = r_waterstate.enabled;
6062 oldcolorscale = r_refdef.view.colorscale;
6063 oldwidth = r_refdef.view.width;
6064 oldheight = r_refdef.view.height;
6065 r_refdef.view.width = r_bloomstate.bloomwidth;
6066 r_refdef.view.height = r_bloomstate.bloomheight;
6068 if(r_hdr.integer < 2)
6069 r_waterstate.enabled = false;
6071 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
6072 // TODO: add exposure compensation features
6073 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6075 r_refdef.view.showdebug = false;
6076 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6078 R_ResetViewRendering3D();
6080 R_ClearScreen(r_refdef.fogenabled);
6081 if (r_timereport_active)
6082 R_TimeReport("HDRclear");
6085 if (r_timereport_active)
6086 R_TimeReport("visibility");
6088 // only do secondary renders with HDR if r_hdr is 2 or higher
6089 r_waterstate.numwaterplanes = 0;
6090 if (r_waterstate.enabled)
6091 R_RenderWaterPlanes();
6093 r_refdef.view.showdebug = true;
6095 r_waterstate.numwaterplanes = 0;
6097 R_ResetViewRendering2D();
6099 R_Bloom_CopyHDRTexture();
6100 R_Bloom_MakeTexture();
6102 // restore the view settings
6103 r_waterstate.enabled = oldwaterstate;
6104 r_refdef.view.width = oldwidth;
6105 r_refdef.view.height = oldheight;
6106 r_refdef.view.colorscale = oldcolorscale;
6108 R_ResetViewRendering3D();
6110 R_ClearScreen(r_refdef.fogenabled);
6111 if (r_timereport_active)
6112 R_TimeReport("viewclear");
6115 static void R_BlendView(void)
6117 unsigned int permutation;
6118 float uservecs[4][4];
6120 switch (vid.renderpath)
6122 case RENDERPATH_GL20:
6123 case RENDERPATH_D3D9:
6124 case RENDERPATH_D3D10:
6125 case RENDERPATH_D3D11:
6126 case RENDERPATH_SOFT:
6127 case RENDERPATH_GLES2:
6129 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6130 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6131 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6132 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6133 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6135 if (r_bloomstate.texture_screen)
6137 // make sure the buffer is available
6138 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6140 R_ResetViewRendering2D();
6141 R_Mesh_SetMainRenderTargets();
6143 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6145 // declare variables
6147 static float avgspeed;
6149 speed = VectorLength(cl.movement_velocity);
6151 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6152 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6154 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6155 speed = bound(0, speed, 1);
6156 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6158 // calculate values into a standard alpha
6159 cl.motionbluralpha = 1 - exp(-
6161 (r_motionblur.value * speed / 80)
6163 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6166 max(0.0001, cl.time - cl.oldtime) // fps independent
6169 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6170 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6172 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6174 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6175 GL_Color(1, 1, 1, cl.motionbluralpha);
6176 switch(vid.renderpath)
6178 case RENDERPATH_GL11:
6179 case RENDERPATH_GL13:
6180 case RENDERPATH_GL20:
6181 case RENDERPATH_GLES1:
6182 case RENDERPATH_GLES2:
6183 case RENDERPATH_SOFT:
6184 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6186 case RENDERPATH_D3D9:
6187 case RENDERPATH_D3D10:
6188 case RENDERPATH_D3D11:
6189 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6192 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6193 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6194 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6198 // copy view into the screen texture
6199 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);
6200 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6202 else if (!r_bloomstate.texture_bloom)
6204 // we may still have to do view tint...
6205 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6207 // apply a color tint to the whole view
6208 R_ResetViewRendering2D();
6209 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6210 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6211 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6212 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6213 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6215 break; // no screen processing, no bloom, skip it
6218 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6220 // render simple bloom effect
6221 // copy the screen and shrink it and darken it for the bloom process
6222 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6223 // make the bloom texture
6224 R_Bloom_MakeTexture();
6227 #if _MSC_VER >= 1400
6228 #define sscanf sscanf_s
6230 memset(uservecs, 0, sizeof(uservecs));
6231 if (r_glsl_postprocess_uservec1_enable.integer)
6232 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6233 if (r_glsl_postprocess_uservec2_enable.integer)
6234 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6235 if (r_glsl_postprocess_uservec3_enable.integer)
6236 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6237 if (r_glsl_postprocess_uservec4_enable.integer)
6238 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6240 R_ResetViewRendering2D();
6241 GL_Color(1, 1, 1, 1);
6242 GL_BlendFunc(GL_ONE, GL_ZERO);
6244 switch(vid.renderpath)
6246 case RENDERPATH_GL20:
6247 case RENDERPATH_GLES2:
6248 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6249 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6250 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6251 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6252 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6253 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]);
6254 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6255 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]);
6256 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]);
6257 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]);
6258 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]);
6259 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6260 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6261 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);
6263 case RENDERPATH_D3D9:
6265 // 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...
6266 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6267 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6268 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6269 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6270 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6271 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6272 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6273 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6274 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6275 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6276 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6277 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6278 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6279 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6282 case RENDERPATH_D3D10:
6283 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6285 case RENDERPATH_D3D11:
6286 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6288 case RENDERPATH_SOFT:
6289 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6290 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6291 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6292 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6293 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6294 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6295 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6296 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6297 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6298 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6299 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6300 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6301 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6302 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6307 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6308 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6310 case RENDERPATH_GL11:
6311 case RENDERPATH_GL13:
6312 case RENDERPATH_GLES1:
6313 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6315 // apply a color tint to the whole view
6316 R_ResetViewRendering2D();
6317 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6318 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6319 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6320 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6321 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6327 matrix4x4_t r_waterscrollmatrix;
6329 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6331 if (r_refdef.fog_density)
6333 r_refdef.fogcolor[0] = r_refdef.fog_red;
6334 r_refdef.fogcolor[1] = r_refdef.fog_green;
6335 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6337 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6338 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6339 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6340 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6344 VectorCopy(r_refdef.fogcolor, fogvec);
6345 // color.rgb *= ContrastBoost * SceneBrightness;
6346 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6347 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6348 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6349 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6354 void R_UpdateVariables(void)
6358 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6360 r_refdef.farclip = r_farclip_base.value;
6361 if (r_refdef.scene.worldmodel)
6362 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6363 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6365 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6366 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6367 r_refdef.polygonfactor = 0;
6368 r_refdef.polygonoffset = 0;
6369 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6370 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6372 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6373 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6374 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6375 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6376 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6377 if (FAKELIGHT_ENABLED)
6379 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6381 if (r_showsurfaces.integer)
6383 r_refdef.scene.rtworld = false;
6384 r_refdef.scene.rtworldshadows = false;
6385 r_refdef.scene.rtdlight = false;
6386 r_refdef.scene.rtdlightshadows = false;
6387 r_refdef.lightmapintensity = 0;
6390 if (gamemode == GAME_NEHAHRA)
6392 if (gl_fogenable.integer)
6394 r_refdef.oldgl_fogenable = true;
6395 r_refdef.fog_density = gl_fogdensity.value;
6396 r_refdef.fog_red = gl_fogred.value;
6397 r_refdef.fog_green = gl_foggreen.value;
6398 r_refdef.fog_blue = gl_fogblue.value;
6399 r_refdef.fog_alpha = 1;
6400 r_refdef.fog_start = 0;
6401 r_refdef.fog_end = gl_skyclip.value;
6402 r_refdef.fog_height = 1<<30;
6403 r_refdef.fog_fadedepth = 128;
6405 else if (r_refdef.oldgl_fogenable)
6407 r_refdef.oldgl_fogenable = false;
6408 r_refdef.fog_density = 0;
6409 r_refdef.fog_red = 0;
6410 r_refdef.fog_green = 0;
6411 r_refdef.fog_blue = 0;
6412 r_refdef.fog_alpha = 0;
6413 r_refdef.fog_start = 0;
6414 r_refdef.fog_end = 0;
6415 r_refdef.fog_height = 1<<30;
6416 r_refdef.fog_fadedepth = 128;
6420 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6421 r_refdef.fog_start = max(0, r_refdef.fog_start);
6422 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6424 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6426 if (r_refdef.fog_density && r_drawfog.integer)
6428 r_refdef.fogenabled = true;
6429 // this is the point where the fog reaches 0.9986 alpha, which we
6430 // consider a good enough cutoff point for the texture
6431 // (0.9986 * 256 == 255.6)
6432 if (r_fog_exp2.integer)
6433 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6435 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6436 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6437 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6438 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6439 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6440 R_BuildFogHeightTexture();
6441 // fog color was already set
6442 // update the fog texture
6443 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)
6444 R_BuildFogTexture();
6445 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6446 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6449 r_refdef.fogenabled = false;
6451 switch(vid.renderpath)
6453 case RENDERPATH_GL20:
6454 case RENDERPATH_D3D9:
6455 case RENDERPATH_D3D10:
6456 case RENDERPATH_D3D11:
6457 case RENDERPATH_SOFT:
6458 case RENDERPATH_GLES2:
6459 if(v_glslgamma.integer && !vid_gammatables_trivial)
6461 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6463 // build GLSL gamma texture
6464 #define RAMPWIDTH 256
6465 unsigned short ramp[RAMPWIDTH * 3];
6466 unsigned char rampbgr[RAMPWIDTH][4];
6469 r_texture_gammaramps_serial = vid_gammatables_serial;
6471 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6472 for(i = 0; i < RAMPWIDTH; ++i)
6474 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6475 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6476 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6479 if (r_texture_gammaramps)
6481 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6485 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6491 // remove GLSL gamma texture
6494 case RENDERPATH_GL11:
6495 case RENDERPATH_GL13:
6496 case RENDERPATH_GLES1:
6501 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6502 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6508 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6509 if( scenetype != r_currentscenetype ) {
6510 // store the old scenetype
6511 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6512 r_currentscenetype = scenetype;
6513 // move in the new scene
6514 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6523 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6525 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6526 if( scenetype == r_currentscenetype ) {
6527 return &r_refdef.scene;
6529 return &r_scenes_store[ scenetype ];
6538 int dpsoftrast_test;
6539 void R_RenderView(void)
6541 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6543 dpsoftrast_test = r_test.integer;
6545 if (r_timereport_active)
6546 R_TimeReport("start");
6547 r_textureframe++; // used only by R_GetCurrentTexture
6548 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6550 if(R_CompileShader_CheckStaticParms())
6553 if (!r_drawentities.integer)
6554 r_refdef.scene.numentities = 0;
6556 R_AnimCache_ClearCache();
6557 R_FrameData_NewFrame();
6559 /* adjust for stereo display */
6560 if(R_Stereo_Active())
6562 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);
6563 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6566 if (r_refdef.view.isoverlay)
6568 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6569 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6570 R_TimeReport("depthclear");
6572 r_refdef.view.showdebug = false;
6574 r_waterstate.enabled = false;
6575 r_waterstate.numwaterplanes = 0;
6579 r_refdef.view.matrix = originalmatrix;
6585 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6587 r_refdef.view.matrix = originalmatrix;
6588 return; //Host_Error ("R_RenderView: NULL worldmodel");
6591 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6593 R_RenderView_UpdateViewVectors();
6595 R_Shadow_UpdateWorldLightSelection();
6597 R_Bloom_StartFrame();
6598 R_Water_StartFrame();
6601 if (r_timereport_active)
6602 R_TimeReport("viewsetup");
6604 R_ResetViewRendering3D();
6606 if (r_refdef.view.clear || r_refdef.fogenabled)
6608 R_ClearScreen(r_refdef.fogenabled);
6609 if (r_timereport_active)
6610 R_TimeReport("viewclear");
6612 r_refdef.view.clear = true;
6614 // this produces a bloom texture to be used in R_BlendView() later
6615 if (r_bloomstate.hdr)
6617 R_HDR_RenderBloomTexture();
6618 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6619 r_textureframe++; // used only by R_GetCurrentTexture
6622 r_refdef.view.showdebug = true;
6625 if (r_timereport_active)
6626 R_TimeReport("visibility");
6628 r_waterstate.numwaterplanes = 0;
6629 if (r_waterstate.enabled)
6630 R_RenderWaterPlanes();
6633 r_waterstate.numwaterplanes = 0;
6636 if (r_timereport_active)
6637 R_TimeReport("blendview");
6639 GL_Scissor(0, 0, vid.width, vid.height);
6640 GL_ScissorTest(false);
6642 r_refdef.view.matrix = originalmatrix;
6647 void R_RenderWaterPlanes(void)
6649 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6651 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6652 if (r_timereport_active)
6653 R_TimeReport("waterworld");
6656 // don't let sound skip if going slow
6657 if (r_refdef.scene.extraupdate)
6660 R_DrawModelsAddWaterPlanes();
6661 if (r_timereport_active)
6662 R_TimeReport("watermodels");
6664 if (r_waterstate.numwaterplanes)
6666 R_Water_ProcessPlanes();
6667 if (r_timereport_active)
6668 R_TimeReport("waterscenes");
6672 extern void R_DrawLightningBeams (void);
6673 extern void VM_CL_AddPolygonsToMeshQueue (void);
6674 extern void R_DrawPortals (void);
6675 extern cvar_t cl_locs_show;
6676 static void R_DrawLocs(void);
6677 static void R_DrawEntityBBoxes(void);
6678 static void R_DrawModelDecals(void);
6679 extern void R_DrawModelShadows(void);
6680 extern void R_DrawModelShadowMaps(void);
6681 extern cvar_t cl_decals_newsystem;
6682 extern qboolean r_shadow_usingdeferredprepass;
6683 void R_RenderScene(void)
6685 qboolean shadowmapping = false;
6687 if (r_timereport_active)
6688 R_TimeReport("beginscene");
6690 r_refdef.stats.renders++;
6694 // don't let sound skip if going slow
6695 if (r_refdef.scene.extraupdate)
6698 R_MeshQueue_BeginScene();
6702 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);
6704 if (r_timereport_active)
6705 R_TimeReport("skystartframe");
6707 if (cl.csqc_vidvars.drawworld)
6709 // don't let sound skip if going slow
6710 if (r_refdef.scene.extraupdate)
6713 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6715 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6716 if (r_timereport_active)
6717 R_TimeReport("worldsky");
6720 if (R_DrawBrushModelsSky() && r_timereport_active)
6721 R_TimeReport("bmodelsky");
6723 if (skyrendermasked && skyrenderlater)
6725 // we have to force off the water clipping plane while rendering sky
6729 if (r_timereport_active)
6730 R_TimeReport("sky");
6734 R_AnimCache_CacheVisibleEntities();
6735 if (r_timereport_active)
6736 R_TimeReport("animation");
6738 R_Shadow_PrepareLights();
6739 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6740 R_Shadow_PrepareModelShadows();
6741 if (r_timereport_active)
6742 R_TimeReport("preparelights");
6744 if (R_Shadow_ShadowMappingEnabled())
6745 shadowmapping = true;
6747 if (r_shadow_usingdeferredprepass)
6748 R_Shadow_DrawPrepass();
6750 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6752 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6753 if (r_timereport_active)
6754 R_TimeReport("worlddepth");
6756 if (r_depthfirst.integer >= 2)
6758 R_DrawModelsDepth();
6759 if (r_timereport_active)
6760 R_TimeReport("modeldepth");
6763 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6765 R_DrawModelShadowMaps();
6766 R_ResetViewRendering3D();
6767 // don't let sound skip if going slow
6768 if (r_refdef.scene.extraupdate)
6772 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6774 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6775 if (r_timereport_active)
6776 R_TimeReport("world");
6779 // don't let sound skip if going slow
6780 if (r_refdef.scene.extraupdate)
6784 if (r_timereport_active)
6785 R_TimeReport("models");
6787 // don't let sound skip if going slow
6788 if (r_refdef.scene.extraupdate)
6791 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6793 R_DrawModelShadows();
6794 R_ResetViewRendering3D();
6795 // don't let sound skip if going slow
6796 if (r_refdef.scene.extraupdate)
6800 if (!r_shadow_usingdeferredprepass)
6802 R_Shadow_DrawLights();
6803 if (r_timereport_active)
6804 R_TimeReport("rtlights");
6807 // don't let sound skip if going slow
6808 if (r_refdef.scene.extraupdate)
6811 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6813 R_DrawModelShadows();
6814 R_ResetViewRendering3D();
6815 // don't let sound skip if going slow
6816 if (r_refdef.scene.extraupdate)
6820 if (cl.csqc_vidvars.drawworld)
6822 if (cl_decals_newsystem.integer)
6824 R_DrawModelDecals();
6825 if (r_timereport_active)
6826 R_TimeReport("modeldecals");
6831 if (r_timereport_active)
6832 R_TimeReport("decals");
6836 if (r_timereport_active)
6837 R_TimeReport("particles");
6840 if (r_timereport_active)
6841 R_TimeReport("explosions");
6843 R_DrawLightningBeams();
6844 if (r_timereport_active)
6845 R_TimeReport("lightning");
6848 VM_CL_AddPolygonsToMeshQueue();
6850 if (r_refdef.view.showdebug)
6852 if (cl_locs_show.integer)
6855 if (r_timereport_active)
6856 R_TimeReport("showlocs");
6859 if (r_drawportals.integer)
6862 if (r_timereport_active)
6863 R_TimeReport("portals");
6866 if (r_showbboxes.value > 0)
6868 R_DrawEntityBBoxes();
6869 if (r_timereport_active)
6870 R_TimeReport("bboxes");
6874 if (r_transparent.integer)
6876 R_MeshQueue_RenderTransparent();
6877 if (r_timereport_active)
6878 R_TimeReport("drawtrans");
6881 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 || r_showoverdraw.value > 0))
6883 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6884 if (r_timereport_active)
6885 R_TimeReport("worlddebug");
6886 R_DrawModelsDebug();
6887 if (r_timereport_active)
6888 R_TimeReport("modeldebug");
6891 if (cl.csqc_vidvars.drawworld)
6893 R_Shadow_DrawCoronas();
6894 if (r_timereport_active)
6895 R_TimeReport("coronas");
6900 GL_DepthTest(false);
6901 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6902 GL_Color(1, 1, 1, 1);
6903 qglBegin(GL_POLYGON);
6904 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6905 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6906 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6907 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6909 qglBegin(GL_POLYGON);
6910 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]);
6911 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]);
6912 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]);
6913 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]);
6915 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6919 // don't let sound skip if going slow
6920 if (r_refdef.scene.extraupdate)
6923 R_ResetViewRendering2D();
6926 static const unsigned short bboxelements[36] =
6936 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6939 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6941 RSurf_ActiveWorldEntity();
6943 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6944 GL_DepthMask(false);
6945 GL_DepthRange(0, 1);
6946 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6947 // R_Mesh_ResetTextureState();
6949 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6950 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6951 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6952 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6953 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6954 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6955 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6956 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6957 R_FillColors(color4f, 8, cr, cg, cb, ca);
6958 if (r_refdef.fogenabled)
6960 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6962 f1 = RSurf_FogVertex(v);
6964 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6965 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6966 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6969 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6970 R_Mesh_ResetTextureState();
6971 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6972 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6975 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6979 prvm_edict_t *edict;
6980 prvm_prog_t *prog_save = prog;
6982 // this function draws bounding boxes of server entities
6986 GL_CullFace(GL_NONE);
6987 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6991 for (i = 0;i < numsurfaces;i++)
6993 edict = PRVM_EDICT_NUM(surfacelist[i]);
6994 switch ((int)edict->fields.server->solid)
6996 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
6997 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
6998 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
6999 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7000 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7001 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7003 color[3] *= r_showbboxes.value;
7004 color[3] = bound(0, color[3], 1);
7005 GL_DepthTest(!r_showdisabledepthtest.integer);
7006 GL_CullFace(r_refdef.view.cullface_front);
7007 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7013 static void R_DrawEntityBBoxes(void)
7016 prvm_edict_t *edict;
7018 prvm_prog_t *prog_save = prog;
7020 // this function draws bounding boxes of server entities
7026 for (i = 0;i < prog->num_edicts;i++)
7028 edict = PRVM_EDICT_NUM(i);
7029 if (edict->priv.server->free)
7031 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7032 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
7034 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
7036 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7037 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7043 static const int nomodelelement3i[24] =
7055 static const unsigned short nomodelelement3s[24] =
7067 static const float nomodelvertex3f[6*3] =
7077 static const float nomodelcolor4f[6*4] =
7079 0.0f, 0.0f, 0.5f, 1.0f,
7080 0.0f, 0.0f, 0.5f, 1.0f,
7081 0.0f, 0.5f, 0.0f, 1.0f,
7082 0.0f, 0.5f, 0.0f, 1.0f,
7083 0.5f, 0.0f, 0.0f, 1.0f,
7084 0.5f, 0.0f, 0.0f, 1.0f
7087 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7093 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);
7095 // this is only called once per entity so numsurfaces is always 1, and
7096 // surfacelist is always {0}, so this code does not handle batches
7098 if (rsurface.ent_flags & RENDER_ADDITIVE)
7100 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7101 GL_DepthMask(false);
7103 else if (rsurface.colormod[3] < 1)
7105 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7106 GL_DepthMask(false);
7110 GL_BlendFunc(GL_ONE, GL_ZERO);
7113 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7114 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7115 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7116 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7117 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7118 for (i = 0, c = color4f;i < 6;i++, c += 4)
7120 c[0] *= rsurface.colormod[0];
7121 c[1] *= rsurface.colormod[1];
7122 c[2] *= rsurface.colormod[2];
7123 c[3] *= rsurface.colormod[3];
7125 if (r_refdef.fogenabled)
7127 for (i = 0, c = color4f;i < 6;i++, c += 4)
7129 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7131 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7132 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7133 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7136 // R_Mesh_ResetTextureState();
7137 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7138 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7139 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7142 void R_DrawNoModel(entity_render_t *ent)
7145 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7146 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7147 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7149 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7152 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7154 vec3_t right1, right2, diff, normal;
7156 VectorSubtract (org2, org1, normal);
7158 // calculate 'right' vector for start
7159 VectorSubtract (r_refdef.view.origin, org1, diff);
7160 CrossProduct (normal, diff, right1);
7161 VectorNormalize (right1);
7163 // calculate 'right' vector for end
7164 VectorSubtract (r_refdef.view.origin, org2, diff);
7165 CrossProduct (normal, diff, right2);
7166 VectorNormalize (right2);
7168 vert[ 0] = org1[0] + width * right1[0];
7169 vert[ 1] = org1[1] + width * right1[1];
7170 vert[ 2] = org1[2] + width * right1[2];
7171 vert[ 3] = org1[0] - width * right1[0];
7172 vert[ 4] = org1[1] - width * right1[1];
7173 vert[ 5] = org1[2] - width * right1[2];
7174 vert[ 6] = org2[0] - width * right2[0];
7175 vert[ 7] = org2[1] - width * right2[1];
7176 vert[ 8] = org2[2] - width * right2[2];
7177 vert[ 9] = org2[0] + width * right2[0];
7178 vert[10] = org2[1] + width * right2[1];
7179 vert[11] = org2[2] + width * right2[2];
7182 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)
7184 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7185 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7186 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7187 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7188 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7189 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7190 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7191 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7192 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7193 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7194 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7195 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7198 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7203 VectorSet(v, x, y, z);
7204 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7205 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7207 if (i == mesh->numvertices)
7209 if (mesh->numvertices < mesh->maxvertices)
7211 VectorCopy(v, vertex3f);
7212 mesh->numvertices++;
7214 return mesh->numvertices;
7220 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7224 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7225 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7226 e = mesh->element3i + mesh->numtriangles * 3;
7227 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7229 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7230 if (mesh->numtriangles < mesh->maxtriangles)
7235 mesh->numtriangles++;
7237 element[1] = element[2];
7241 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7245 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7246 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7247 e = mesh->element3i + mesh->numtriangles * 3;
7248 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7250 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7251 if (mesh->numtriangles < mesh->maxtriangles)
7256 mesh->numtriangles++;
7258 element[1] = element[2];
7262 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7263 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7265 int planenum, planenum2;
7268 mplane_t *plane, *plane2;
7270 double temppoints[2][256*3];
7271 // figure out how large a bounding box we need to properly compute this brush
7273 for (w = 0;w < numplanes;w++)
7274 maxdist = max(maxdist, fabs(planes[w].dist));
7275 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7276 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7277 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7281 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7282 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7284 if (planenum2 == planenum)
7286 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);
7289 if (tempnumpoints < 3)
7291 // generate elements forming a triangle fan for this polygon
7292 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7296 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)
7298 texturelayer_t *layer;
7299 layer = t->currentlayers + t->currentnumlayers++;
7301 layer->depthmask = depthmask;
7302 layer->blendfunc1 = blendfunc1;
7303 layer->blendfunc2 = blendfunc2;
7304 layer->texture = texture;
7305 layer->texmatrix = *matrix;
7306 layer->color[0] = r;
7307 layer->color[1] = g;
7308 layer->color[2] = b;
7309 layer->color[3] = a;
7312 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7314 if(parms[0] == 0 && parms[1] == 0)
7316 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7317 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7322 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7325 index = parms[2] + r_refdef.scene.time * parms[3];
7326 index -= floor(index);
7327 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7330 case Q3WAVEFUNC_NONE:
7331 case Q3WAVEFUNC_NOISE:
7332 case Q3WAVEFUNC_COUNT:
7335 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7336 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7337 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7338 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7339 case Q3WAVEFUNC_TRIANGLE:
7341 f = index - floor(index);
7352 f = parms[0] + parms[1] * f;
7353 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7354 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7358 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7363 matrix4x4_t matrix, temp;
7364 switch(tcmod->tcmod)
7368 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7369 matrix = r_waterscrollmatrix;
7371 matrix = identitymatrix;
7373 case Q3TCMOD_ENTITYTRANSLATE:
7374 // this is used in Q3 to allow the gamecode to control texcoord
7375 // scrolling on the entity, which is not supported in darkplaces yet.
7376 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7378 case Q3TCMOD_ROTATE:
7379 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7380 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7381 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7384 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7386 case Q3TCMOD_SCROLL:
7387 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7389 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7390 w = (int) tcmod->parms[0];
7391 h = (int) tcmod->parms[1];
7392 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7394 idx = (int) floor(f * w * h);
7395 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7397 case Q3TCMOD_STRETCH:
7398 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7399 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7401 case Q3TCMOD_TRANSFORM:
7402 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7403 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7404 VectorSet(tcmat + 6, 0 , 0 , 1);
7405 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7406 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7408 case Q3TCMOD_TURBULENT:
7409 // this is handled in the RSurf_PrepareVertices function
7410 matrix = identitymatrix;
7414 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7417 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7419 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7420 char name[MAX_QPATH];
7421 skinframe_t *skinframe;
7422 unsigned char pixels[296*194];
7423 strlcpy(cache->name, skinname, sizeof(cache->name));
7424 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7425 if (developer_loading.integer)
7426 Con_Printf("loading %s\n", name);
7427 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7428 if (!skinframe || !skinframe->base)
7431 fs_offset_t filesize;
7433 f = FS_LoadFile(name, tempmempool, true, &filesize);
7436 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7437 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7441 cache->skinframe = skinframe;
7444 texture_t *R_GetCurrentTexture(texture_t *t)
7447 const entity_render_t *ent = rsurface.entity;
7448 dp_model_t *model = ent->model;
7449 q3shaderinfo_layer_tcmod_t *tcmod;
7451 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7452 return t->currentframe;
7453 t->update_lastrenderframe = r_textureframe;
7454 t->update_lastrenderentity = (void *)ent;
7456 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7457 t->camera_entity = ent->entitynumber;
7459 t->camera_entity = 0;
7461 // switch to an alternate material if this is a q1bsp animated material
7463 texture_t *texture = t;
7464 int s = rsurface.ent_skinnum;
7465 if ((unsigned int)s >= (unsigned int)model->numskins)
7467 if (model->skinscenes)
7469 if (model->skinscenes[s].framecount > 1)
7470 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7472 s = model->skinscenes[s].firstframe;
7475 t = t + s * model->num_surfaces;
7478 // use an alternate animation if the entity's frame is not 0,
7479 // and only if the texture has an alternate animation
7480 if (rsurface.ent_alttextures && t->anim_total[1])
7481 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7483 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7485 texture->currentframe = t;
7488 // update currentskinframe to be a qw skin or animation frame
7489 if (rsurface.ent_qwskin >= 0)
7491 i = rsurface.ent_qwskin;
7492 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7494 r_qwskincache_size = cl.maxclients;
7496 Mem_Free(r_qwskincache);
7497 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7499 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7500 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7501 t->currentskinframe = r_qwskincache[i].skinframe;
7502 if (t->currentskinframe == NULL)
7503 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7505 else if (t->numskinframes >= 2)
7506 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7507 if (t->backgroundnumskinframes >= 2)
7508 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7510 t->currentmaterialflags = t->basematerialflags;
7511 t->currentalpha = rsurface.colormod[3];
7512 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7513 t->currentalpha *= r_wateralpha.value;
7514 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7515 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7516 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7517 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7518 if (!(rsurface.ent_flags & RENDER_LIGHT))
7519 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7520 else if (FAKELIGHT_ENABLED)
7522 // no modellight if using fakelight for the map
7524 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7526 // pick a model lighting mode
7527 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7528 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7530 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7532 if (rsurface.ent_flags & RENDER_ADDITIVE)
7533 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7534 else if (t->currentalpha < 1)
7535 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7536 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7537 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7538 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7539 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7540 if (t->backgroundnumskinframes)
7541 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7542 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7544 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7545 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7548 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7549 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7550 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7552 // there is no tcmod
7553 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7555 t->currenttexmatrix = r_waterscrollmatrix;
7556 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7558 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7560 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7561 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7564 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7565 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7566 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7567 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7569 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7570 if (t->currentskinframe->qpixels)
7571 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7572 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7573 if (!t->basetexture)
7574 t->basetexture = r_texture_notexture;
7575 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7576 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7577 t->nmaptexture = t->currentskinframe->nmap;
7578 if (!t->nmaptexture)
7579 t->nmaptexture = r_texture_blanknormalmap;
7580 t->glosstexture = r_texture_black;
7581 t->glowtexture = t->currentskinframe->glow;
7582 t->fogtexture = t->currentskinframe->fog;
7583 t->reflectmasktexture = t->currentskinframe->reflect;
7584 if (t->backgroundnumskinframes)
7586 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7587 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7588 t->backgroundglosstexture = r_texture_black;
7589 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7590 if (!t->backgroundnmaptexture)
7591 t->backgroundnmaptexture = r_texture_blanknormalmap;
7595 t->backgroundbasetexture = r_texture_white;
7596 t->backgroundnmaptexture = r_texture_blanknormalmap;
7597 t->backgroundglosstexture = r_texture_black;
7598 t->backgroundglowtexture = NULL;
7600 t->specularpower = r_shadow_glossexponent.value;
7601 // TODO: store reference values for these in the texture?
7602 t->specularscale = 0;
7603 if (r_shadow_gloss.integer > 0)
7605 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7607 if (r_shadow_glossintensity.value > 0)
7609 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7610 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7611 t->specularscale = r_shadow_glossintensity.value;
7614 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7616 t->glosstexture = r_texture_white;
7617 t->backgroundglosstexture = r_texture_white;
7618 t->specularscale = r_shadow_gloss2intensity.value;
7619 t->specularpower = r_shadow_gloss2exponent.value;
7622 t->specularscale *= t->specularscalemod;
7623 t->specularpower *= t->specularpowermod;
7625 // lightmaps mode looks bad with dlights using actual texturing, so turn
7626 // off the colormap and glossmap, but leave the normalmap on as it still
7627 // accurately represents the shading involved
7628 if (gl_lightmaps.integer)
7630 t->basetexture = r_texture_grey128;
7631 t->pantstexture = r_texture_black;
7632 t->shirttexture = r_texture_black;
7633 t->nmaptexture = r_texture_blanknormalmap;
7634 t->glosstexture = r_texture_black;
7635 t->glowtexture = NULL;
7636 t->fogtexture = NULL;
7637 t->reflectmasktexture = NULL;
7638 t->backgroundbasetexture = NULL;
7639 t->backgroundnmaptexture = r_texture_blanknormalmap;
7640 t->backgroundglosstexture = r_texture_black;
7641 t->backgroundglowtexture = NULL;
7642 t->specularscale = 0;
7643 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7646 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7647 VectorClear(t->dlightcolor);
7648 t->currentnumlayers = 0;
7649 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7651 int blendfunc1, blendfunc2;
7653 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7655 blendfunc1 = GL_SRC_ALPHA;
7656 blendfunc2 = GL_ONE;
7658 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7660 blendfunc1 = GL_SRC_ALPHA;
7661 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7663 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7665 blendfunc1 = t->customblendfunc[0];
7666 blendfunc2 = t->customblendfunc[1];
7670 blendfunc1 = GL_ONE;
7671 blendfunc2 = GL_ZERO;
7673 // don't colormod evilblend textures
7674 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7675 VectorSet(t->lightmapcolor, 1, 1, 1);
7676 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7677 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7679 // fullbright is not affected by r_refdef.lightmapintensity
7680 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]);
7681 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7682 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]);
7683 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7684 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]);
7688 vec3_t ambientcolor;
7690 // set the color tint used for lights affecting this surface
7691 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7693 // q3bsp has no lightmap updates, so the lightstylevalue that
7694 // would normally be baked into the lightmap must be
7695 // applied to the color
7696 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7697 if (model->type == mod_brushq3)
7698 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7699 colorscale *= r_refdef.lightmapintensity;
7700 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7701 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7702 // basic lit geometry
7703 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]);
7704 // add pants/shirt if needed
7705 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7706 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]);
7707 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7708 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]);
7709 // now add ambient passes if needed
7710 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7712 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]);
7713 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7714 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]);
7715 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7716 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]);
7719 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7720 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]);
7721 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7723 // if this is opaque use alpha blend which will darken the earlier
7726 // if this is an alpha blended material, all the earlier passes
7727 // were darkened by fog already, so we only need to add the fog
7728 // color ontop through the fog mask texture
7730 // if this is an additive blended material, all the earlier passes
7731 // were darkened by fog already, and we should not add fog color
7732 // (because the background was not darkened, there is no fog color
7733 // that was lost behind it).
7734 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]);
7738 return t->currentframe;
7741 rsurfacestate_t rsurface;
7743 void RSurf_ActiveWorldEntity(void)
7745 dp_model_t *model = r_refdef.scene.worldmodel;
7746 //if (rsurface.entity == r_refdef.scene.worldentity)
7748 rsurface.entity = r_refdef.scene.worldentity;
7749 rsurface.skeleton = NULL;
7750 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7751 rsurface.ent_skinnum = 0;
7752 rsurface.ent_qwskin = -1;
7753 rsurface.ent_shadertime = 0;
7754 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7755 rsurface.matrix = identitymatrix;
7756 rsurface.inversematrix = identitymatrix;
7757 rsurface.matrixscale = 1;
7758 rsurface.inversematrixscale = 1;
7759 R_EntityMatrix(&identitymatrix);
7760 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7761 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7762 rsurface.fograngerecip = r_refdef.fograngerecip;
7763 rsurface.fogheightfade = r_refdef.fogheightfade;
7764 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7765 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7766 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7767 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7768 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7769 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7770 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7771 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7772 rsurface.colormod[3] = 1;
7773 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);
7774 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7775 rsurface.frameblend[0].lerp = 1;
7776 rsurface.ent_alttextures = false;
7777 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7778 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7779 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7780 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7781 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7782 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7783 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7784 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7785 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7786 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7787 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7788 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7789 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7790 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7791 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7792 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7793 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7794 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7795 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7796 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7797 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7798 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7799 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7800 rsurface.modelelement3i = model->surfmesh.data_element3i;
7801 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7802 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7803 rsurface.modelelement3s = model->surfmesh.data_element3s;
7804 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7805 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7806 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7807 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7808 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7809 rsurface.modelsurfaces = model->data_surfaces;
7810 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7811 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7812 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7813 rsurface.modelgeneratedvertex = false;
7814 rsurface.batchgeneratedvertex = false;
7815 rsurface.batchfirstvertex = 0;
7816 rsurface.batchnumvertices = 0;
7817 rsurface.batchfirsttriangle = 0;
7818 rsurface.batchnumtriangles = 0;
7819 rsurface.batchvertex3f = NULL;
7820 rsurface.batchvertex3f_vertexbuffer = NULL;
7821 rsurface.batchvertex3f_bufferoffset = 0;
7822 rsurface.batchsvector3f = NULL;
7823 rsurface.batchsvector3f_vertexbuffer = NULL;
7824 rsurface.batchsvector3f_bufferoffset = 0;
7825 rsurface.batchtvector3f = NULL;
7826 rsurface.batchtvector3f_vertexbuffer = NULL;
7827 rsurface.batchtvector3f_bufferoffset = 0;
7828 rsurface.batchnormal3f = NULL;
7829 rsurface.batchnormal3f_vertexbuffer = NULL;
7830 rsurface.batchnormal3f_bufferoffset = 0;
7831 rsurface.batchlightmapcolor4f = NULL;
7832 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7833 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7834 rsurface.batchtexcoordtexture2f = NULL;
7835 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7836 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7837 rsurface.batchtexcoordlightmap2f = NULL;
7838 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7839 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7840 rsurface.batchvertexmesh = NULL;
7841 rsurface.batchvertexmeshbuffer = NULL;
7842 rsurface.batchvertex3fbuffer = NULL;
7843 rsurface.batchelement3i = NULL;
7844 rsurface.batchelement3i_indexbuffer = NULL;
7845 rsurface.batchelement3i_bufferoffset = 0;
7846 rsurface.batchelement3s = NULL;
7847 rsurface.batchelement3s_indexbuffer = NULL;
7848 rsurface.batchelement3s_bufferoffset = 0;
7849 rsurface.passcolor4f = NULL;
7850 rsurface.passcolor4f_vertexbuffer = NULL;
7851 rsurface.passcolor4f_bufferoffset = 0;
7854 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7856 dp_model_t *model = ent->model;
7857 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7859 rsurface.entity = (entity_render_t *)ent;
7860 rsurface.skeleton = ent->skeleton;
7861 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7862 rsurface.ent_skinnum = ent->skinnum;
7863 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;
7864 rsurface.ent_shadertime = ent->shadertime;
7865 rsurface.ent_flags = ent->flags;
7866 rsurface.matrix = ent->matrix;
7867 rsurface.inversematrix = ent->inversematrix;
7868 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7869 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7870 R_EntityMatrix(&rsurface.matrix);
7871 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7872 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7873 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7874 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7875 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7876 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7877 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7878 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7879 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7880 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7881 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7882 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7883 rsurface.colormod[3] = ent->alpha;
7884 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7885 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7886 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7887 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7888 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7889 if (ent->model->brush.submodel && !prepass)
7891 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7892 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7894 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7896 if (ent->animcache_vertex3f)
7898 rsurface.modelvertex3f = ent->animcache_vertex3f;
7899 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7900 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7901 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7902 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7903 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7904 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7906 else if (wanttangents)
7908 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7909 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7910 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7911 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7912 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7913 rsurface.modelvertexmesh = NULL;
7914 rsurface.modelvertexmeshbuffer = NULL;
7915 rsurface.modelvertex3fbuffer = NULL;
7917 else if (wantnormals)
7919 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7920 rsurface.modelsvector3f = NULL;
7921 rsurface.modeltvector3f = NULL;
7922 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7923 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7924 rsurface.modelvertexmesh = NULL;
7925 rsurface.modelvertexmeshbuffer = NULL;
7926 rsurface.modelvertex3fbuffer = NULL;
7930 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7931 rsurface.modelsvector3f = NULL;
7932 rsurface.modeltvector3f = NULL;
7933 rsurface.modelnormal3f = NULL;
7934 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7935 rsurface.modelvertexmesh = NULL;
7936 rsurface.modelvertexmeshbuffer = NULL;
7937 rsurface.modelvertex3fbuffer = NULL;
7939 rsurface.modelvertex3f_vertexbuffer = 0;
7940 rsurface.modelvertex3f_bufferoffset = 0;
7941 rsurface.modelsvector3f_vertexbuffer = 0;
7942 rsurface.modelsvector3f_bufferoffset = 0;
7943 rsurface.modeltvector3f_vertexbuffer = 0;
7944 rsurface.modeltvector3f_bufferoffset = 0;
7945 rsurface.modelnormal3f_vertexbuffer = 0;
7946 rsurface.modelnormal3f_bufferoffset = 0;
7947 rsurface.modelgeneratedvertex = true;
7951 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7952 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7953 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7954 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7955 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7956 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7957 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7958 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7959 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7960 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7961 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7962 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7963 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7964 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7965 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7966 rsurface.modelgeneratedvertex = false;
7968 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7969 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7970 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7971 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7972 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7973 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7974 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7975 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7976 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7977 rsurface.modelelement3i = model->surfmesh.data_element3i;
7978 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7979 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7980 rsurface.modelelement3s = model->surfmesh.data_element3s;
7981 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7982 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7983 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7984 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7985 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7986 rsurface.modelsurfaces = model->data_surfaces;
7987 rsurface.batchgeneratedvertex = false;
7988 rsurface.batchfirstvertex = 0;
7989 rsurface.batchnumvertices = 0;
7990 rsurface.batchfirsttriangle = 0;
7991 rsurface.batchnumtriangles = 0;
7992 rsurface.batchvertex3f = NULL;
7993 rsurface.batchvertex3f_vertexbuffer = NULL;
7994 rsurface.batchvertex3f_bufferoffset = 0;
7995 rsurface.batchsvector3f = NULL;
7996 rsurface.batchsvector3f_vertexbuffer = NULL;
7997 rsurface.batchsvector3f_bufferoffset = 0;
7998 rsurface.batchtvector3f = NULL;
7999 rsurface.batchtvector3f_vertexbuffer = NULL;
8000 rsurface.batchtvector3f_bufferoffset = 0;
8001 rsurface.batchnormal3f = NULL;
8002 rsurface.batchnormal3f_vertexbuffer = NULL;
8003 rsurface.batchnormal3f_bufferoffset = 0;
8004 rsurface.batchlightmapcolor4f = NULL;
8005 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8006 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8007 rsurface.batchtexcoordtexture2f = NULL;
8008 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8009 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8010 rsurface.batchtexcoordlightmap2f = NULL;
8011 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8012 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8013 rsurface.batchvertexmesh = NULL;
8014 rsurface.batchvertexmeshbuffer = NULL;
8015 rsurface.batchvertex3fbuffer = NULL;
8016 rsurface.batchelement3i = NULL;
8017 rsurface.batchelement3i_indexbuffer = NULL;
8018 rsurface.batchelement3i_bufferoffset = 0;
8019 rsurface.batchelement3s = NULL;
8020 rsurface.batchelement3s_indexbuffer = NULL;
8021 rsurface.batchelement3s_bufferoffset = 0;
8022 rsurface.passcolor4f = NULL;
8023 rsurface.passcolor4f_vertexbuffer = NULL;
8024 rsurface.passcolor4f_bufferoffset = 0;
8027 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)
8029 rsurface.entity = r_refdef.scene.worldentity;
8030 rsurface.skeleton = NULL;
8031 rsurface.ent_skinnum = 0;
8032 rsurface.ent_qwskin = -1;
8033 rsurface.ent_shadertime = shadertime;
8034 rsurface.ent_flags = entflags;
8035 rsurface.modelnumvertices = numvertices;
8036 rsurface.modelnumtriangles = numtriangles;
8037 rsurface.matrix = *matrix;
8038 rsurface.inversematrix = *inversematrix;
8039 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8040 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8041 R_EntityMatrix(&rsurface.matrix);
8042 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8043 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8044 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8045 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8046 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8047 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8048 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8049 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8050 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8051 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8052 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8053 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8054 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);
8055 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8056 rsurface.frameblend[0].lerp = 1;
8057 rsurface.ent_alttextures = false;
8058 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8059 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8062 rsurface.modelvertex3f = (float *)vertex3f;
8063 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8064 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8065 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8067 else if (wantnormals)
8069 rsurface.modelvertex3f = (float *)vertex3f;
8070 rsurface.modelsvector3f = NULL;
8071 rsurface.modeltvector3f = NULL;
8072 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8076 rsurface.modelvertex3f = (float *)vertex3f;
8077 rsurface.modelsvector3f = NULL;
8078 rsurface.modeltvector3f = NULL;
8079 rsurface.modelnormal3f = NULL;
8081 rsurface.modelvertexmesh = NULL;
8082 rsurface.modelvertexmeshbuffer = NULL;
8083 rsurface.modelvertex3fbuffer = NULL;
8084 rsurface.modelvertex3f_vertexbuffer = 0;
8085 rsurface.modelvertex3f_bufferoffset = 0;
8086 rsurface.modelsvector3f_vertexbuffer = 0;
8087 rsurface.modelsvector3f_bufferoffset = 0;
8088 rsurface.modeltvector3f_vertexbuffer = 0;
8089 rsurface.modeltvector3f_bufferoffset = 0;
8090 rsurface.modelnormal3f_vertexbuffer = 0;
8091 rsurface.modelnormal3f_bufferoffset = 0;
8092 rsurface.modelgeneratedvertex = true;
8093 rsurface.modellightmapcolor4f = (float *)color4f;
8094 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8095 rsurface.modellightmapcolor4f_bufferoffset = 0;
8096 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8097 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8098 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8099 rsurface.modeltexcoordlightmap2f = NULL;
8100 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8101 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8102 rsurface.modelelement3i = (int *)element3i;
8103 rsurface.modelelement3i_indexbuffer = NULL;
8104 rsurface.modelelement3i_bufferoffset = 0;
8105 rsurface.modelelement3s = (unsigned short *)element3s;
8106 rsurface.modelelement3s_indexbuffer = NULL;
8107 rsurface.modelelement3s_bufferoffset = 0;
8108 rsurface.modellightmapoffsets = NULL;
8109 rsurface.modelsurfaces = NULL;
8110 rsurface.batchgeneratedvertex = false;
8111 rsurface.batchfirstvertex = 0;
8112 rsurface.batchnumvertices = 0;
8113 rsurface.batchfirsttriangle = 0;
8114 rsurface.batchnumtriangles = 0;
8115 rsurface.batchvertex3f = NULL;
8116 rsurface.batchvertex3f_vertexbuffer = NULL;
8117 rsurface.batchvertex3f_bufferoffset = 0;
8118 rsurface.batchsvector3f = NULL;
8119 rsurface.batchsvector3f_vertexbuffer = NULL;
8120 rsurface.batchsvector3f_bufferoffset = 0;
8121 rsurface.batchtvector3f = NULL;
8122 rsurface.batchtvector3f_vertexbuffer = NULL;
8123 rsurface.batchtvector3f_bufferoffset = 0;
8124 rsurface.batchnormal3f = NULL;
8125 rsurface.batchnormal3f_vertexbuffer = NULL;
8126 rsurface.batchnormal3f_bufferoffset = 0;
8127 rsurface.batchlightmapcolor4f = NULL;
8128 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8129 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8130 rsurface.batchtexcoordtexture2f = NULL;
8131 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8132 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8133 rsurface.batchtexcoordlightmap2f = NULL;
8134 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8135 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8136 rsurface.batchvertexmesh = NULL;
8137 rsurface.batchvertexmeshbuffer = NULL;
8138 rsurface.batchvertex3fbuffer = NULL;
8139 rsurface.batchelement3i = NULL;
8140 rsurface.batchelement3i_indexbuffer = NULL;
8141 rsurface.batchelement3i_bufferoffset = 0;
8142 rsurface.batchelement3s = NULL;
8143 rsurface.batchelement3s_indexbuffer = NULL;
8144 rsurface.batchelement3s_bufferoffset = 0;
8145 rsurface.passcolor4f = NULL;
8146 rsurface.passcolor4f_vertexbuffer = NULL;
8147 rsurface.passcolor4f_bufferoffset = 0;
8149 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8151 if ((wantnormals || wanttangents) && !normal3f)
8153 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8154 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8156 if (wanttangents && !svector3f)
8158 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8159 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8160 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8165 float RSurf_FogPoint(const float *v)
8167 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8168 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8169 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8170 float FogHeightFade = r_refdef.fogheightfade;
8172 unsigned int fogmasktableindex;
8173 if (r_refdef.fogplaneviewabove)
8174 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8176 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8177 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8178 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8181 float RSurf_FogVertex(const float *v)
8183 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8184 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8185 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8186 float FogHeightFade = rsurface.fogheightfade;
8188 unsigned int fogmasktableindex;
8189 if (r_refdef.fogplaneviewabove)
8190 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8192 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8193 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8194 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8197 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8200 for (i = 0;i < numelements;i++)
8201 outelement3i[i] = inelement3i[i] + adjust;
8204 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8205 extern cvar_t gl_vbo;
8206 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8214 int surfacefirsttriangle;
8215 int surfacenumtriangles;
8216 int surfacefirstvertex;
8217 int surfaceendvertex;
8218 int surfacenumvertices;
8219 int batchnumvertices;
8220 int batchnumtriangles;
8224 qboolean dynamicvertex;
8228 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8230 q3shaderinfo_deform_t *deform;
8231 const msurface_t *surface, *firstsurface;
8232 r_vertexmesh_t *vertexmesh;
8233 if (!texturenumsurfaces)
8235 // find vertex range of this surface batch
8237 firstsurface = texturesurfacelist[0];
8238 firsttriangle = firstsurface->num_firsttriangle;
8239 batchnumvertices = 0;
8240 batchnumtriangles = 0;
8241 firstvertex = endvertex = firstsurface->num_firstvertex;
8242 for (i = 0;i < texturenumsurfaces;i++)
8244 surface = texturesurfacelist[i];
8245 if (surface != firstsurface + i)
8247 surfacefirstvertex = surface->num_firstvertex;
8248 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8249 surfacenumvertices = surface->num_vertices;
8250 surfacenumtriangles = surface->num_triangles;
8251 if (firstvertex > surfacefirstvertex)
8252 firstvertex = surfacefirstvertex;
8253 if (endvertex < surfaceendvertex)
8254 endvertex = surfaceendvertex;
8255 batchnumvertices += surfacenumvertices;
8256 batchnumtriangles += surfacenumtriangles;
8259 // we now know the vertex range used, and if there are any gaps in it
8260 rsurface.batchfirstvertex = firstvertex;
8261 rsurface.batchnumvertices = endvertex - firstvertex;
8262 rsurface.batchfirsttriangle = firsttriangle;
8263 rsurface.batchnumtriangles = batchnumtriangles;
8265 // this variable holds flags for which properties have been updated that
8266 // may require regenerating vertexmesh array...
8269 // check if any dynamic vertex processing must occur
8270 dynamicvertex = false;
8272 // if there is a chance of animated vertex colors, it's a dynamic batch
8273 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8275 dynamicvertex = true;
8276 batchneed |= BATCHNEED_NOGAPS;
8277 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8280 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8282 switch (deform->deform)
8285 case Q3DEFORM_PROJECTIONSHADOW:
8286 case Q3DEFORM_TEXT0:
8287 case Q3DEFORM_TEXT1:
8288 case Q3DEFORM_TEXT2:
8289 case Q3DEFORM_TEXT3:
8290 case Q3DEFORM_TEXT4:
8291 case Q3DEFORM_TEXT5:
8292 case Q3DEFORM_TEXT6:
8293 case Q3DEFORM_TEXT7:
8296 case Q3DEFORM_AUTOSPRITE:
8297 dynamicvertex = true;
8298 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8299 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8301 case Q3DEFORM_AUTOSPRITE2:
8302 dynamicvertex = true;
8303 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8304 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8306 case Q3DEFORM_NORMAL:
8307 dynamicvertex = true;
8308 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8309 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8312 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8313 break; // if wavefunc is a nop, ignore this transform
8314 dynamicvertex = true;
8315 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8316 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8318 case Q3DEFORM_BULGE:
8319 dynamicvertex = true;
8320 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8321 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8324 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8325 break; // if wavefunc is a nop, ignore this transform
8326 dynamicvertex = true;
8327 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8328 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8332 switch(rsurface.texture->tcgen.tcgen)
8335 case Q3TCGEN_TEXTURE:
8337 case Q3TCGEN_LIGHTMAP:
8338 dynamicvertex = true;
8339 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8340 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8342 case Q3TCGEN_VECTOR:
8343 dynamicvertex = true;
8344 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8345 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8347 case Q3TCGEN_ENVIRONMENT:
8348 dynamicvertex = true;
8349 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8350 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8353 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8355 dynamicvertex = true;
8356 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8357 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8360 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8362 dynamicvertex = true;
8363 batchneed |= BATCHNEED_NOGAPS;
8364 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8367 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8369 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8370 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8371 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8372 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8373 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8374 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8375 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8378 // when the model data has no vertex buffer (dynamic mesh), we need to
8380 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8381 batchneed |= BATCHNEED_NOGAPS;
8383 // if needsupdate, we have to do a dynamic vertex batch for sure
8384 if (needsupdate & batchneed)
8385 dynamicvertex = true;
8387 // see if we need to build vertexmesh from arrays
8388 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8389 dynamicvertex = true;
8391 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8392 // also some drivers strongly dislike firstvertex
8393 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8394 dynamicvertex = true;
8396 rsurface.batchvertex3f = rsurface.modelvertex3f;
8397 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8398 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8399 rsurface.batchsvector3f = rsurface.modelsvector3f;
8400 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8401 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8402 rsurface.batchtvector3f = rsurface.modeltvector3f;
8403 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8404 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8405 rsurface.batchnormal3f = rsurface.modelnormal3f;
8406 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8407 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8408 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8409 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8410 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8411 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8412 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8413 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8414 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8415 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8416 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8417 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8418 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8419 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8420 rsurface.batchelement3i = rsurface.modelelement3i;
8421 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8422 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8423 rsurface.batchelement3s = rsurface.modelelement3s;
8424 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8425 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8427 // if any dynamic vertex processing has to occur in software, we copy the
8428 // entire surface list together before processing to rebase the vertices
8429 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8431 // if any gaps exist and we do not have a static vertex buffer, we have to
8432 // copy the surface list together to avoid wasting upload bandwidth on the
8433 // vertices in the gaps.
8435 // if gaps exist and we have a static vertex buffer, we still have to
8436 // combine the index buffer ranges into one dynamic index buffer.
8438 // in all cases we end up with data that can be drawn in one call.
8442 // static vertex data, just set pointers...
8443 rsurface.batchgeneratedvertex = false;
8444 // if there are gaps, we want to build a combined index buffer,
8445 // otherwise use the original static buffer with an appropriate offset
8448 // build a new triangle elements array for this batch
8449 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8450 rsurface.batchfirsttriangle = 0;
8452 for (i = 0;i < texturenumsurfaces;i++)
8454 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8455 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8456 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8457 numtriangles += surfacenumtriangles;
8459 rsurface.batchelement3i_indexbuffer = NULL;
8460 rsurface.batchelement3i_bufferoffset = 0;
8461 rsurface.batchelement3s = NULL;
8462 rsurface.batchelement3s_indexbuffer = NULL;
8463 rsurface.batchelement3s_bufferoffset = 0;
8464 if (endvertex <= 65536)
8466 // make a 16bit (unsigned short) index array if possible
8467 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8468 for (i = 0;i < numtriangles*3;i++)
8469 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8475 // something needs software processing, do it for real...
8476 // we only directly handle separate array data in this case and then
8477 // generate interleaved data if needed...
8478 rsurface.batchgeneratedvertex = true;
8480 // now copy the vertex data into a combined array and make an index array
8481 // (this is what Quake3 does all the time)
8482 //if (gaps || rsurface.batchfirstvertex)
8484 rsurface.batchvertex3fbuffer = NULL;
8485 rsurface.batchvertexmesh = NULL;
8486 rsurface.batchvertexmeshbuffer = NULL;
8487 rsurface.batchvertex3f = NULL;
8488 rsurface.batchvertex3f_vertexbuffer = NULL;
8489 rsurface.batchvertex3f_bufferoffset = 0;
8490 rsurface.batchsvector3f = NULL;
8491 rsurface.batchsvector3f_vertexbuffer = NULL;
8492 rsurface.batchsvector3f_bufferoffset = 0;
8493 rsurface.batchtvector3f = NULL;
8494 rsurface.batchtvector3f_vertexbuffer = NULL;
8495 rsurface.batchtvector3f_bufferoffset = 0;
8496 rsurface.batchnormal3f = NULL;
8497 rsurface.batchnormal3f_vertexbuffer = NULL;
8498 rsurface.batchnormal3f_bufferoffset = 0;
8499 rsurface.batchlightmapcolor4f = NULL;
8500 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8501 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8502 rsurface.batchtexcoordtexture2f = NULL;
8503 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8504 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8505 rsurface.batchtexcoordlightmap2f = NULL;
8506 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8507 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8508 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8509 rsurface.batchelement3i_indexbuffer = NULL;
8510 rsurface.batchelement3i_bufferoffset = 0;
8511 rsurface.batchelement3s = NULL;
8512 rsurface.batchelement3s_indexbuffer = NULL;
8513 rsurface.batchelement3s_bufferoffset = 0;
8514 // we'll only be setting up certain arrays as needed
8515 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8516 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8517 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8518 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8519 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8520 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8521 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8523 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8524 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8526 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8527 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8528 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8529 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8530 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8531 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8534 for (i = 0;i < texturenumsurfaces;i++)
8536 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8537 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8538 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8539 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8540 // copy only the data requested
8541 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8542 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8543 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8545 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8546 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8547 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8548 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8549 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8551 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8552 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8554 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8555 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8556 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8557 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8558 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8559 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8561 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8562 numvertices += surfacenumvertices;
8563 numtriangles += surfacenumtriangles;
8566 // generate a 16bit index array as well if possible
8567 // (in general, dynamic batches fit)
8568 if (numvertices <= 65536)
8570 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8571 for (i = 0;i < numtriangles*3;i++)
8572 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8575 // since we've copied everything, the batch now starts at 0
8576 rsurface.batchfirstvertex = 0;
8577 rsurface.batchnumvertices = batchnumvertices;
8578 rsurface.batchfirsttriangle = 0;
8579 rsurface.batchnumtriangles = batchnumtriangles;
8582 // q1bsp surfaces rendered in vertex color mode have to have colors
8583 // calculated based on lightstyles
8584 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8586 // generate color arrays for the surfaces in this list
8591 const unsigned char *lm;
8592 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8593 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8594 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8596 for (i = 0;i < texturenumsurfaces;i++)
8598 surface = texturesurfacelist[i];
8599 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8600 surfacenumvertices = surface->num_vertices;
8601 if (surface->lightmapinfo->samples)
8603 for (j = 0;j < surfacenumvertices;j++)
8605 lm = surface->lightmapinfo->samples + offsets[j];
8606 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8607 VectorScale(lm, scale, c);
8608 if (surface->lightmapinfo->styles[1] != 255)
8610 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8612 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8613 VectorMA(c, scale, lm, c);
8614 if (surface->lightmapinfo->styles[2] != 255)
8617 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8618 VectorMA(c, scale, lm, c);
8619 if (surface->lightmapinfo->styles[3] != 255)
8622 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8623 VectorMA(c, scale, lm, c);
8630 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);
8636 for (j = 0;j < surfacenumvertices;j++)
8638 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8645 // if vertices are deformed (sprite flares and things in maps, possibly
8646 // water waves, bulges and other deformations), modify the copied vertices
8648 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8650 switch (deform->deform)
8653 case Q3DEFORM_PROJECTIONSHADOW:
8654 case Q3DEFORM_TEXT0:
8655 case Q3DEFORM_TEXT1:
8656 case Q3DEFORM_TEXT2:
8657 case Q3DEFORM_TEXT3:
8658 case Q3DEFORM_TEXT4:
8659 case Q3DEFORM_TEXT5:
8660 case Q3DEFORM_TEXT6:
8661 case Q3DEFORM_TEXT7:
8664 case Q3DEFORM_AUTOSPRITE:
8665 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8666 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8667 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8668 VectorNormalize(newforward);
8669 VectorNormalize(newright);
8670 VectorNormalize(newup);
8671 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8672 // rsurface.batchvertex3f_vertexbuffer = NULL;
8673 // rsurface.batchvertex3f_bufferoffset = 0;
8674 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8675 // rsurface.batchsvector3f_vertexbuffer = NULL;
8676 // rsurface.batchsvector3f_bufferoffset = 0;
8677 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8678 // rsurface.batchtvector3f_vertexbuffer = NULL;
8679 // rsurface.batchtvector3f_bufferoffset = 0;
8680 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8681 // rsurface.batchnormal3f_vertexbuffer = NULL;
8682 // rsurface.batchnormal3f_bufferoffset = 0;
8683 // a single autosprite surface can contain multiple sprites...
8684 for (j = 0;j < batchnumvertices - 3;j += 4)
8686 VectorClear(center);
8687 for (i = 0;i < 4;i++)
8688 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8689 VectorScale(center, 0.25f, center);
8690 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8691 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8692 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8693 for (i = 0;i < 4;i++)
8695 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8696 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8699 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8700 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8701 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);
8703 case Q3DEFORM_AUTOSPRITE2:
8704 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8705 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8706 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8707 VectorNormalize(newforward);
8708 VectorNormalize(newright);
8709 VectorNormalize(newup);
8710 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8711 // rsurface.batchvertex3f_vertexbuffer = NULL;
8712 // rsurface.batchvertex3f_bufferoffset = 0;
8714 const float *v1, *v2;
8724 memset(shortest, 0, sizeof(shortest));
8725 // a single autosprite surface can contain multiple sprites...
8726 for (j = 0;j < batchnumvertices - 3;j += 4)
8728 VectorClear(center);
8729 for (i = 0;i < 4;i++)
8730 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8731 VectorScale(center, 0.25f, center);
8732 // find the two shortest edges, then use them to define the
8733 // axis vectors for rotating around the central axis
8734 for (i = 0;i < 6;i++)
8736 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8737 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8738 l = VectorDistance2(v1, v2);
8739 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8741 l += (1.0f / 1024.0f);
8742 if (shortest[0].length2 > l || i == 0)
8744 shortest[1] = shortest[0];
8745 shortest[0].length2 = l;
8746 shortest[0].v1 = v1;
8747 shortest[0].v2 = v2;
8749 else if (shortest[1].length2 > l || i == 1)
8751 shortest[1].length2 = l;
8752 shortest[1].v1 = v1;
8753 shortest[1].v2 = v2;
8756 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8757 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8758 // this calculates the right vector from the shortest edge
8759 // and the up vector from the edge midpoints
8760 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8761 VectorNormalize(right);
8762 VectorSubtract(end, start, up);
8763 VectorNormalize(up);
8764 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8765 VectorSubtract(rsurface.localvieworigin, center, forward);
8766 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8767 VectorNegate(forward, forward);
8768 VectorReflect(forward, 0, up, forward);
8769 VectorNormalize(forward);
8770 CrossProduct(up, forward, newright);
8771 VectorNormalize(newright);
8772 // rotate the quad around the up axis vector, this is made
8773 // especially easy by the fact we know the quad is flat,
8774 // so we only have to subtract the center position and
8775 // measure distance along the right vector, and then
8776 // multiply that by the newright vector and add back the
8778 // we also need to subtract the old position to undo the
8779 // displacement from the center, which we do with a
8780 // DotProduct, the subtraction/addition of center is also
8781 // optimized into DotProducts here
8782 l = DotProduct(right, center);
8783 for (i = 0;i < 4;i++)
8785 v1 = rsurface.batchvertex3f + 3*(j+i);
8786 f = DotProduct(right, v1) - l;
8787 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8791 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8793 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8794 // rsurface.batchnormal3f_vertexbuffer = NULL;
8795 // rsurface.batchnormal3f_bufferoffset = 0;
8796 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8798 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8800 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8801 // rsurface.batchsvector3f_vertexbuffer = NULL;
8802 // rsurface.batchsvector3f_bufferoffset = 0;
8803 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8804 // rsurface.batchtvector3f_vertexbuffer = NULL;
8805 // rsurface.batchtvector3f_bufferoffset = 0;
8806 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);
8809 case Q3DEFORM_NORMAL:
8810 // deform the normals to make reflections wavey
8811 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8812 rsurface.batchnormal3f_vertexbuffer = NULL;
8813 rsurface.batchnormal3f_bufferoffset = 0;
8814 for (j = 0;j < batchnumvertices;j++)
8817 float *normal = rsurface.batchnormal3f + 3*j;
8818 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8819 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8820 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]);
8821 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]);
8822 VectorNormalize(normal);
8824 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8826 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8827 // rsurface.batchsvector3f_vertexbuffer = NULL;
8828 // rsurface.batchsvector3f_bufferoffset = 0;
8829 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8830 // rsurface.batchtvector3f_vertexbuffer = NULL;
8831 // rsurface.batchtvector3f_bufferoffset = 0;
8832 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);
8836 // deform vertex array to make wavey water and flags and such
8837 waveparms[0] = deform->waveparms[0];
8838 waveparms[1] = deform->waveparms[1];
8839 waveparms[2] = deform->waveparms[2];
8840 waveparms[3] = deform->waveparms[3];
8841 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8842 break; // if wavefunc is a nop, don't make a dynamic vertex array
8843 // this is how a divisor of vertex influence on deformation
8844 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8845 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8846 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8847 // rsurface.batchvertex3f_vertexbuffer = NULL;
8848 // rsurface.batchvertex3f_bufferoffset = 0;
8849 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8850 // rsurface.batchnormal3f_vertexbuffer = NULL;
8851 // rsurface.batchnormal3f_bufferoffset = 0;
8852 for (j = 0;j < batchnumvertices;j++)
8854 // if the wavefunc depends on time, evaluate it per-vertex
8857 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8858 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8860 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8862 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8863 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8864 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8866 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8867 // rsurface.batchsvector3f_vertexbuffer = NULL;
8868 // rsurface.batchsvector3f_bufferoffset = 0;
8869 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8870 // rsurface.batchtvector3f_vertexbuffer = NULL;
8871 // rsurface.batchtvector3f_bufferoffset = 0;
8872 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);
8875 case Q3DEFORM_BULGE:
8876 // deform vertex array to make the surface have moving bulges
8877 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8878 // rsurface.batchvertex3f_vertexbuffer = NULL;
8879 // rsurface.batchvertex3f_bufferoffset = 0;
8880 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8881 // rsurface.batchnormal3f_vertexbuffer = NULL;
8882 // rsurface.batchnormal3f_bufferoffset = 0;
8883 for (j = 0;j < batchnumvertices;j++)
8885 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8886 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8888 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8889 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8890 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8892 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8893 // rsurface.batchsvector3f_vertexbuffer = NULL;
8894 // rsurface.batchsvector3f_bufferoffset = 0;
8895 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8896 // rsurface.batchtvector3f_vertexbuffer = NULL;
8897 // rsurface.batchtvector3f_bufferoffset = 0;
8898 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);
8902 // deform vertex array
8903 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8904 break; // if wavefunc is a nop, don't make a dynamic vertex array
8905 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8906 VectorScale(deform->parms, scale, waveparms);
8907 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8908 // rsurface.batchvertex3f_vertexbuffer = NULL;
8909 // rsurface.batchvertex3f_bufferoffset = 0;
8910 for (j = 0;j < batchnumvertices;j++)
8911 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8916 // generate texcoords based on the chosen texcoord source
8917 switch(rsurface.texture->tcgen.tcgen)
8920 case Q3TCGEN_TEXTURE:
8922 case Q3TCGEN_LIGHTMAP:
8923 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8924 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8925 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8926 if (rsurface.batchtexcoordlightmap2f)
8927 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8929 case Q3TCGEN_VECTOR:
8930 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8931 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8932 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8933 for (j = 0;j < batchnumvertices;j++)
8935 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8936 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8939 case Q3TCGEN_ENVIRONMENT:
8940 // make environment reflections using a spheremap
8941 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8942 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8943 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8944 for (j = 0;j < batchnumvertices;j++)
8946 // identical to Q3A's method, but executed in worldspace so
8947 // carried models can be shiny too
8949 float viewer[3], d, reflected[3], worldreflected[3];
8951 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8952 // VectorNormalize(viewer);
8954 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8956 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8957 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8958 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8959 // note: this is proportinal to viewer, so we can normalize later
8961 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8962 VectorNormalize(worldreflected);
8964 // note: this sphere map only uses world x and z!
8965 // so positive and negative y will LOOK THE SAME.
8966 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8967 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8971 // the only tcmod that needs software vertex processing is turbulent, so
8972 // check for it here and apply the changes if needed
8973 // and we only support that as the first one
8974 // (handling a mixture of turbulent and other tcmods would be problematic
8975 // without punting it entirely to a software path)
8976 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8978 amplitude = rsurface.texture->tcmods[0].parms[1];
8979 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8980 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8981 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8982 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8983 for (j = 0;j < batchnumvertices;j++)
8985 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);
8986 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8990 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8992 // convert the modified arrays to vertex structs
8993 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8994 // rsurface.batchvertexmeshbuffer = NULL;
8995 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8996 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8997 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8998 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8999 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9000 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9001 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9003 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9005 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9006 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9009 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9010 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9011 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9012 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9013 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9014 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9015 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9016 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9017 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9021 void RSurf_DrawBatch(void)
9023 // sometimes a zero triangle surface (usually a degenerate patch) makes it
9024 // through the pipeline, killing it earlier in the pipeline would have
9025 // per-surface overhead rather than per-batch overhead, so it's best to
9026 // reject it here, before it hits glDraw.
9027 if (rsurface.batchnumtriangles == 0)
9030 // batch debugging code
9031 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9037 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9038 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9041 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9043 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9045 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9046 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);
9053 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);
9056 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9058 // pick the closest matching water plane
9059 int planeindex, vertexindex, bestplaneindex = -1;
9063 r_waterstate_waterplane_t *p;
9064 qboolean prepared = false;
9066 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9068 if(p->camera_entity != rsurface.texture->camera_entity)
9073 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9075 if(rsurface.batchnumvertices == 0)
9078 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9080 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9081 d += fabs(PlaneDiff(vert, &p->plane));
9083 if (bestd > d || bestplaneindex < 0)
9086 bestplaneindex = planeindex;
9089 return bestplaneindex;
9090 // NOTE: this MAY return a totally unrelated water plane; we can ignore
9091 // this situation though, as it might be better to render single larger
9092 // batches with useless stuff (backface culled for example) than to
9093 // render multiple smaller batches
9096 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9099 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9100 rsurface.passcolor4f_vertexbuffer = 0;
9101 rsurface.passcolor4f_bufferoffset = 0;
9102 for (i = 0;i < rsurface.batchnumvertices;i++)
9103 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9106 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9113 if (rsurface.passcolor4f)
9115 // generate color arrays
9116 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9117 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9118 rsurface.passcolor4f_vertexbuffer = 0;
9119 rsurface.passcolor4f_bufferoffset = 0;
9120 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)
9122 f = RSurf_FogVertex(v);
9131 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9132 rsurface.passcolor4f_vertexbuffer = 0;
9133 rsurface.passcolor4f_bufferoffset = 0;
9134 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9136 f = RSurf_FogVertex(v);
9145 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9152 if (!rsurface.passcolor4f)
9154 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9155 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9156 rsurface.passcolor4f_vertexbuffer = 0;
9157 rsurface.passcolor4f_bufferoffset = 0;
9158 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)
9160 f = RSurf_FogVertex(v);
9161 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9162 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9163 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9168 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9173 if (!rsurface.passcolor4f)
9175 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9176 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9177 rsurface.passcolor4f_vertexbuffer = 0;
9178 rsurface.passcolor4f_bufferoffset = 0;
9179 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9188 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9193 if (!rsurface.passcolor4f)
9195 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9196 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9197 rsurface.passcolor4f_vertexbuffer = 0;
9198 rsurface.passcolor4f_bufferoffset = 0;
9199 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9201 c2[0] = c[0] + r_refdef.scene.ambient;
9202 c2[1] = c[1] + r_refdef.scene.ambient;
9203 c2[2] = c[2] + r_refdef.scene.ambient;
9208 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9211 rsurface.passcolor4f = NULL;
9212 rsurface.passcolor4f_vertexbuffer = 0;
9213 rsurface.passcolor4f_bufferoffset = 0;
9214 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9215 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9216 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9217 GL_Color(r, g, b, a);
9218 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9222 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9224 // TODO: optimize applyfog && applycolor case
9225 // just apply fog if necessary, and tint the fog color array if necessary
9226 rsurface.passcolor4f = NULL;
9227 rsurface.passcolor4f_vertexbuffer = 0;
9228 rsurface.passcolor4f_bufferoffset = 0;
9229 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9230 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9231 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9232 GL_Color(r, g, b, a);
9236 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9239 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9240 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9241 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9242 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9243 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9244 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9245 GL_Color(r, g, b, a);
9249 static void RSurf_DrawBatch_GL11_ClampColor(void)
9254 if (!rsurface.passcolor4f)
9256 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9258 c2[0] = bound(0.0f, c1[0], 1.0f);
9259 c2[1] = bound(0.0f, c1[1], 1.0f);
9260 c2[2] = bound(0.0f, c1[2], 1.0f);
9261 c2[3] = bound(0.0f, c1[3], 1.0f);
9265 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9275 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9276 rsurface.passcolor4f_vertexbuffer = 0;
9277 rsurface.passcolor4f_bufferoffset = 0;
9278 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)
9280 f = -DotProduct(r_refdef.view.forward, n);
9282 f = f * 0.85 + 0.15; // work around so stuff won't get black
9283 f *= r_refdef.lightmapintensity;
9284 Vector4Set(c, f, f, f, 1);
9288 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9290 RSurf_DrawBatch_GL11_ApplyFakeLight();
9291 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9292 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9293 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9294 GL_Color(r, g, b, a);
9298 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9306 vec3_t ambientcolor;
9307 vec3_t diffusecolor;
9311 VectorCopy(rsurface.modellight_lightdir, lightdir);
9312 f = 0.5f * r_refdef.lightmapintensity;
9313 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9314 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9315 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9316 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9317 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9318 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9320 if (VectorLength2(diffusecolor) > 0)
9322 // q3-style directional shading
9323 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9324 rsurface.passcolor4f_vertexbuffer = 0;
9325 rsurface.passcolor4f_bufferoffset = 0;
9326 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)
9328 if ((f = DotProduct(n, lightdir)) > 0)
9329 VectorMA(ambientcolor, f, diffusecolor, c);
9331 VectorCopy(ambientcolor, c);
9338 *applycolor = false;
9342 *r = ambientcolor[0];
9343 *g = ambientcolor[1];
9344 *b = ambientcolor[2];
9345 rsurface.passcolor4f = NULL;
9346 rsurface.passcolor4f_vertexbuffer = 0;
9347 rsurface.passcolor4f_bufferoffset = 0;
9351 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9353 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9354 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9355 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9356 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9357 GL_Color(r, g, b, a);
9361 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9369 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9370 rsurface.passcolor4f_vertexbuffer = 0;
9371 rsurface.passcolor4f_bufferoffset = 0;
9373 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9375 f = 1 - RSurf_FogVertex(v);
9383 void RSurf_SetupDepthAndCulling(void)
9385 // submodels are biased to avoid z-fighting with world surfaces that they
9386 // may be exactly overlapping (avoids z-fighting artifacts on certain
9387 // doors and things in Quake maps)
9388 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9389 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9390 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9391 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9394 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9396 // transparent sky would be ridiculous
9397 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9399 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9400 skyrenderlater = true;
9401 RSurf_SetupDepthAndCulling();
9403 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9404 // skymasking on them, and Quake3 never did sky masking (unlike
9405 // software Quake and software Quake2), so disable the sky masking
9406 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9407 // and skymasking also looks very bad when noclipping outside the
9408 // level, so don't use it then either.
9409 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9411 R_Mesh_ResetTextureState();
9412 if (skyrendermasked)
9414 R_SetupShader_DepthOrShadow();
9415 // depth-only (masking)
9416 GL_ColorMask(0,0,0,0);
9417 // just to make sure that braindead drivers don't draw
9418 // anything despite that colormask...
9419 GL_BlendFunc(GL_ZERO, GL_ONE);
9420 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9421 if (rsurface.batchvertex3fbuffer)
9422 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9424 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9428 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9430 GL_BlendFunc(GL_ONE, GL_ZERO);
9431 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9432 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9433 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9436 if (skyrendermasked)
9437 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9439 R_Mesh_ResetTextureState();
9440 GL_Color(1, 1, 1, 1);
9443 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9444 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9445 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9447 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9451 // render screenspace normalmap to texture
9453 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9458 // bind lightmap texture
9460 // water/refraction/reflection/camera surfaces have to be handled specially
9461 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9463 int start, end, startplaneindex;
9464 for (start = 0;start < texturenumsurfaces;start = end)
9466 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9467 if(startplaneindex < 0)
9469 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9470 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9474 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9476 // now that we have a batch using the same planeindex, render it
9477 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9479 // render water or distortion background
9481 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));
9483 // blend surface on top
9484 GL_DepthMask(false);
9485 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9488 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9490 // render surface with reflection texture as input
9491 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9492 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));
9499 // render surface batch normally
9500 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9501 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9505 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9507 // OpenGL 1.3 path - anything not completely ancient
9508 qboolean applycolor;
9511 const texturelayer_t *layer;
9512 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);
9513 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9515 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9518 int layertexrgbscale;
9519 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9521 if (layerindex == 0)
9525 GL_AlphaTest(false);
9526 GL_DepthFunc(GL_EQUAL);
9529 GL_DepthMask(layer->depthmask && writedepth);
9530 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9531 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9533 layertexrgbscale = 4;
9534 VectorScale(layer->color, 0.25f, layercolor);
9536 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9538 layertexrgbscale = 2;
9539 VectorScale(layer->color, 0.5f, layercolor);
9543 layertexrgbscale = 1;
9544 VectorScale(layer->color, 1.0f, layercolor);
9546 layercolor[3] = layer->color[3];
9547 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9548 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9549 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9550 switch (layer->type)
9552 case TEXTURELAYERTYPE_LITTEXTURE:
9553 // single-pass lightmapped texture with 2x rgbscale
9554 R_Mesh_TexBind(0, r_texture_white);
9555 R_Mesh_TexMatrix(0, NULL);
9556 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9557 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9558 R_Mesh_TexBind(1, layer->texture);
9559 R_Mesh_TexMatrix(1, &layer->texmatrix);
9560 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9561 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9562 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9563 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9564 else if (FAKELIGHT_ENABLED)
9565 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9566 else if (rsurface.uselightmaptexture)
9567 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9569 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9571 case TEXTURELAYERTYPE_TEXTURE:
9572 // singletexture unlit texture with transparency support
9573 R_Mesh_TexBind(0, layer->texture);
9574 R_Mesh_TexMatrix(0, &layer->texmatrix);
9575 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9576 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9577 R_Mesh_TexBind(1, 0);
9578 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9579 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9581 case TEXTURELAYERTYPE_FOG:
9582 // singletexture fogging
9585 R_Mesh_TexBind(0, layer->texture);
9586 R_Mesh_TexMatrix(0, &layer->texmatrix);
9587 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9588 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9592 R_Mesh_TexBind(0, 0);
9593 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9595 R_Mesh_TexBind(1, 0);
9596 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9597 // generate a color array for the fog pass
9598 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9599 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9603 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9606 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9608 GL_DepthFunc(GL_LEQUAL);
9609 GL_AlphaTest(false);
9613 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9615 // OpenGL 1.1 - crusty old voodoo path
9618 const texturelayer_t *layer;
9619 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);
9620 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9622 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9624 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9626 if (layerindex == 0)
9630 GL_AlphaTest(false);
9631 GL_DepthFunc(GL_EQUAL);
9634 GL_DepthMask(layer->depthmask && writedepth);
9635 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9636 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9637 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9638 switch (layer->type)
9640 case TEXTURELAYERTYPE_LITTEXTURE:
9641 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9643 // two-pass lit texture with 2x rgbscale
9644 // first the lightmap pass
9645 R_Mesh_TexBind(0, r_texture_white);
9646 R_Mesh_TexMatrix(0, NULL);
9647 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9648 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9649 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9650 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9651 else if (FAKELIGHT_ENABLED)
9652 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9653 else if (rsurface.uselightmaptexture)
9654 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9656 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9657 // then apply the texture to it
9658 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9659 R_Mesh_TexBind(0, layer->texture);
9660 R_Mesh_TexMatrix(0, &layer->texmatrix);
9661 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9662 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9663 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);
9667 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9668 R_Mesh_TexBind(0, layer->texture);
9669 R_Mesh_TexMatrix(0, &layer->texmatrix);
9670 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9671 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9672 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9673 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);
9675 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);
9678 case TEXTURELAYERTYPE_TEXTURE:
9679 // singletexture unlit texture with transparency support
9680 R_Mesh_TexBind(0, layer->texture);
9681 R_Mesh_TexMatrix(0, &layer->texmatrix);
9682 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9683 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9684 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);
9686 case TEXTURELAYERTYPE_FOG:
9687 // singletexture fogging
9690 R_Mesh_TexBind(0, layer->texture);
9691 R_Mesh_TexMatrix(0, &layer->texmatrix);
9692 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9693 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9697 R_Mesh_TexBind(0, 0);
9698 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9700 // generate a color array for the fog pass
9701 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9702 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9706 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9709 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9711 GL_DepthFunc(GL_LEQUAL);
9712 GL_AlphaTest(false);
9716 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9720 r_vertexgeneric_t *batchvertex;
9723 // R_Mesh_ResetTextureState();
9724 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9726 if(rsurface.texture && rsurface.texture->currentskinframe)
9728 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9729 c[3] *= rsurface.texture->currentalpha;
9739 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9741 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9742 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9743 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9746 // brighten it up (as texture value 127 means "unlit")
9747 c[0] *= 2 * r_refdef.view.colorscale;
9748 c[1] *= 2 * r_refdef.view.colorscale;
9749 c[2] *= 2 * r_refdef.view.colorscale;
9751 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9752 c[3] *= r_wateralpha.value;
9754 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9756 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9757 GL_DepthMask(false);
9759 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9761 GL_BlendFunc(GL_ONE, GL_ONE);
9762 GL_DepthMask(false);
9764 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9766 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9767 GL_DepthMask(false);
9769 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9771 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9772 GL_DepthMask(false);
9776 GL_BlendFunc(GL_ONE, GL_ZERO);
9777 GL_DepthMask(writedepth);
9780 if (r_showsurfaces.integer == 3)
9782 rsurface.passcolor4f = NULL;
9784 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9786 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9788 rsurface.passcolor4f = NULL;
9789 rsurface.passcolor4f_vertexbuffer = 0;
9790 rsurface.passcolor4f_bufferoffset = 0;
9792 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9794 qboolean applycolor = true;
9797 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9799 r_refdef.lightmapintensity = 1;
9800 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9801 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9803 else if (FAKELIGHT_ENABLED)
9805 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9807 r_refdef.lightmapintensity = r_fakelight_intensity.value;
9808 RSurf_DrawBatch_GL11_ApplyFakeLight();
9809 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9813 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9815 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9816 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9817 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9820 if(!rsurface.passcolor4f)
9821 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9823 RSurf_DrawBatch_GL11_ApplyAmbient();
9824 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9825 if(r_refdef.fogenabled)
9826 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9827 RSurf_DrawBatch_GL11_ClampColor();
9829 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9830 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9833 else if (!r_refdef.view.showdebug)
9835 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9836 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9837 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9839 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9840 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9842 R_Mesh_PrepareVertices_Generic_Unlock();
9845 else if (r_showsurfaces.integer == 4)
9847 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9848 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9849 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9851 unsigned char c = (vi << 3) * (1.0f / 256.0f);
9852 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9853 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9855 R_Mesh_PrepareVertices_Generic_Unlock();
9858 else if (r_showsurfaces.integer == 2)
9861 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9862 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9863 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9865 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9866 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9867 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9868 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9869 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9870 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9871 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9873 R_Mesh_PrepareVertices_Generic_Unlock();
9874 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9878 int texturesurfaceindex;
9880 const msurface_t *surface;
9881 float surfacecolor4f[4];
9882 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9883 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9885 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9887 surface = texturesurfacelist[texturesurfaceindex];
9888 k = (int)(((size_t)surface) / sizeof(msurface_t));
9889 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9890 for (j = 0;j < surface->num_vertices;j++)
9892 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9893 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9897 R_Mesh_PrepareVertices_Generic_Unlock();
9902 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9905 RSurf_SetupDepthAndCulling();
9906 if (r_showsurfaces.integer)
9908 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9911 switch (vid.renderpath)
9913 case RENDERPATH_GL20:
9914 case RENDERPATH_D3D9:
9915 case RENDERPATH_D3D10:
9916 case RENDERPATH_D3D11:
9917 case RENDERPATH_SOFT:
9918 case RENDERPATH_GLES2:
9919 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9921 case RENDERPATH_GL13:
9922 case RENDERPATH_GLES1:
9923 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9925 case RENDERPATH_GL11:
9926 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9932 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9935 RSurf_SetupDepthAndCulling();
9936 if (r_showsurfaces.integer)
9938 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9941 switch (vid.renderpath)
9943 case RENDERPATH_GL20:
9944 case RENDERPATH_D3D9:
9945 case RENDERPATH_D3D10:
9946 case RENDERPATH_D3D11:
9947 case RENDERPATH_SOFT:
9948 case RENDERPATH_GLES2:
9949 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9951 case RENDERPATH_GL13:
9952 case RENDERPATH_GLES1:
9953 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9955 case RENDERPATH_GL11:
9956 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9962 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9965 int texturenumsurfaces, endsurface;
9967 const msurface_t *surface;
9968 #define MAXBATCH_TRANSPARENTSURFACES 256
9969 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9971 // if the model is static it doesn't matter what value we give for
9972 // wantnormals and wanttangents, so this logic uses only rules applicable
9973 // to a model, knowing that they are meaningless otherwise
9974 if (ent == r_refdef.scene.worldentity)
9975 RSurf_ActiveWorldEntity();
9976 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9977 RSurf_ActiveModelEntity(ent, false, false, false);
9980 switch (vid.renderpath)
9982 case RENDERPATH_GL20:
9983 case RENDERPATH_D3D9:
9984 case RENDERPATH_D3D10:
9985 case RENDERPATH_D3D11:
9986 case RENDERPATH_SOFT:
9987 case RENDERPATH_GLES2:
9988 RSurf_ActiveModelEntity(ent, true, true, false);
9990 case RENDERPATH_GL11:
9991 case RENDERPATH_GL13:
9992 case RENDERPATH_GLES1:
9993 RSurf_ActiveModelEntity(ent, true, false, false);
9998 if (r_transparentdepthmasking.integer)
10000 qboolean setup = false;
10001 for (i = 0;i < numsurfaces;i = j)
10004 surface = rsurface.modelsurfaces + surfacelist[i];
10005 texture = surface->texture;
10006 rsurface.texture = R_GetCurrentTexture(texture);
10007 rsurface.lightmaptexture = NULL;
10008 rsurface.deluxemaptexture = NULL;
10009 rsurface.uselightmaptexture = false;
10010 // scan ahead until we find a different texture
10011 endsurface = min(i + 1024, numsurfaces);
10012 texturenumsurfaces = 0;
10013 texturesurfacelist[texturenumsurfaces++] = surface;
10014 for (;j < endsurface;j++)
10016 surface = rsurface.modelsurfaces + surfacelist[j];
10017 if (texture != surface->texture)
10019 texturesurfacelist[texturenumsurfaces++] = surface;
10021 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10023 // render the range of surfaces as depth
10027 GL_ColorMask(0,0,0,0);
10029 GL_DepthTest(true);
10030 GL_BlendFunc(GL_ONE, GL_ZERO);
10031 GL_DepthMask(true);
10032 // R_Mesh_ResetTextureState();
10033 R_SetupShader_DepthOrShadow();
10035 RSurf_SetupDepthAndCulling();
10036 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10037 if (rsurface.batchvertex3fbuffer)
10038 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10040 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10044 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10047 for (i = 0;i < numsurfaces;i = j)
10050 surface = rsurface.modelsurfaces + surfacelist[i];
10051 texture = surface->texture;
10052 rsurface.texture = R_GetCurrentTexture(texture);
10053 // scan ahead until we find a different texture
10054 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
10055 texturenumsurfaces = 0;
10056 texturesurfacelist[texturenumsurfaces++] = surface;
10057 if(FAKELIGHT_ENABLED)
10059 rsurface.lightmaptexture = NULL;
10060 rsurface.deluxemaptexture = NULL;
10061 rsurface.uselightmaptexture = false;
10062 for (;j < endsurface;j++)
10064 surface = rsurface.modelsurfaces + surfacelist[j];
10065 if (texture != surface->texture)
10067 texturesurfacelist[texturenumsurfaces++] = surface;
10072 rsurface.lightmaptexture = surface->lightmaptexture;
10073 rsurface.deluxemaptexture = surface->deluxemaptexture;
10074 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10075 for (;j < endsurface;j++)
10077 surface = rsurface.modelsurfaces + surfacelist[j];
10078 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10080 texturesurfacelist[texturenumsurfaces++] = surface;
10083 // render the range of surfaces
10084 if (ent == r_refdef.scene.worldentity)
10085 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10087 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10089 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10092 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10094 // transparent surfaces get pushed off into the transparent queue
10095 int surfacelistindex;
10096 const msurface_t *surface;
10097 vec3_t tempcenter, center;
10098 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10100 surface = texturesurfacelist[surfacelistindex];
10101 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10102 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10103 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10104 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10105 if (queueentity->transparent_offset) // transparent offset
10107 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10108 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10109 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10111 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10115 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10117 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10119 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10121 RSurf_SetupDepthAndCulling();
10122 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10123 if (rsurface.batchvertex3fbuffer)
10124 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10126 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10130 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10132 const entity_render_t *queueentity = r_refdef.scene.worldentity;
10135 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10138 if (!rsurface.texture->currentnumlayers)
10140 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10141 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10143 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10145 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10146 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10147 else if (!rsurface.texture->currentnumlayers)
10149 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10151 // in the deferred case, transparent surfaces were queued during prepass
10152 if (!r_shadow_usingdeferredprepass)
10153 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10157 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10158 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10163 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10166 texture_t *texture;
10167 R_FrameData_SetMark();
10168 // break the surface list down into batches by texture and use of lightmapping
10169 for (i = 0;i < numsurfaces;i = j)
10172 // texture is the base texture pointer, rsurface.texture is the
10173 // current frame/skin the texture is directing us to use (for example
10174 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10175 // use skin 1 instead)
10176 texture = surfacelist[i]->texture;
10177 rsurface.texture = R_GetCurrentTexture(texture);
10178 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10180 // if this texture is not the kind we want, skip ahead to the next one
10181 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10185 if(FAKELIGHT_ENABLED || depthonly || prepass)
10187 rsurface.lightmaptexture = NULL;
10188 rsurface.deluxemaptexture = NULL;
10189 rsurface.uselightmaptexture = false;
10190 // simply scan ahead until we find a different texture or lightmap state
10191 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10196 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10197 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10198 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10199 // simply scan ahead until we find a different texture or lightmap state
10200 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10203 // render the range of surfaces
10204 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10206 R_FrameData_ReturnToMark();
10209 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10213 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10216 if (!rsurface.texture->currentnumlayers)
10218 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10219 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10221 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10223 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10224 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10225 else if (!rsurface.texture->currentnumlayers)
10227 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10229 // in the deferred case, transparent surfaces were queued during prepass
10230 if (!r_shadow_usingdeferredprepass)
10231 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10235 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10236 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10241 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10244 texture_t *texture;
10245 R_FrameData_SetMark();
10246 // break the surface list down into batches by texture and use of lightmapping
10247 for (i = 0;i < numsurfaces;i = j)
10250 // texture is the base texture pointer, rsurface.texture is the
10251 // current frame/skin the texture is directing us to use (for example
10252 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10253 // use skin 1 instead)
10254 texture = surfacelist[i]->texture;
10255 rsurface.texture = R_GetCurrentTexture(texture);
10256 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10258 // if this texture is not the kind we want, skip ahead to the next one
10259 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10263 if(FAKELIGHT_ENABLED || depthonly || prepass)
10265 rsurface.lightmaptexture = NULL;
10266 rsurface.deluxemaptexture = NULL;
10267 rsurface.uselightmaptexture = false;
10268 // simply scan ahead until we find a different texture or lightmap state
10269 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10274 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10275 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10276 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10277 // simply scan ahead until we find a different texture or lightmap state
10278 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10281 // render the range of surfaces
10282 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10284 R_FrameData_ReturnToMark();
10287 float locboxvertex3f[6*4*3] =
10289 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10290 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10291 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10292 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10293 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10294 1,0,0, 0,0,0, 0,1,0, 1,1,0
10297 unsigned short locboxelements[6*2*3] =
10302 12,13,14, 12,14,15,
10303 16,17,18, 16,18,19,
10307 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10310 cl_locnode_t *loc = (cl_locnode_t *)ent;
10312 float vertex3f[6*4*3];
10314 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10315 GL_DepthMask(false);
10316 GL_DepthRange(0, 1);
10317 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10318 GL_DepthTest(true);
10319 GL_CullFace(GL_NONE);
10320 R_EntityMatrix(&identitymatrix);
10322 // R_Mesh_ResetTextureState();
10324 i = surfacelist[0];
10325 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10326 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10327 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10328 surfacelist[0] < 0 ? 0.5f : 0.125f);
10330 if (VectorCompare(loc->mins, loc->maxs))
10332 VectorSet(size, 2, 2, 2);
10333 VectorMA(loc->mins, -0.5f, size, mins);
10337 VectorCopy(loc->mins, mins);
10338 VectorSubtract(loc->maxs, loc->mins, size);
10341 for (i = 0;i < 6*4*3;)
10342 for (j = 0;j < 3;j++, i++)
10343 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10345 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10346 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10347 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10350 void R_DrawLocs(void)
10353 cl_locnode_t *loc, *nearestloc;
10355 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10356 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10358 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10359 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10363 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10365 if (decalsystem->decals)
10366 Mem_Free(decalsystem->decals);
10367 memset(decalsystem, 0, sizeof(*decalsystem));
10370 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)
10373 tridecal_t *decals;
10376 // expand or initialize the system
10377 if (decalsystem->maxdecals <= decalsystem->numdecals)
10379 decalsystem_t old = *decalsystem;
10380 qboolean useshortelements;
10381 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10382 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10383 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)));
10384 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10385 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10386 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10387 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10388 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10389 if (decalsystem->numdecals)
10390 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10392 Mem_Free(old.decals);
10393 for (i = 0;i < decalsystem->maxdecals*3;i++)
10394 decalsystem->element3i[i] = i;
10395 if (useshortelements)
10396 for (i = 0;i < decalsystem->maxdecals*3;i++)
10397 decalsystem->element3s[i] = i;
10400 // grab a decal and search for another free slot for the next one
10401 decals = decalsystem->decals;
10402 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10403 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10405 decalsystem->freedecal = i;
10406 if (decalsystem->numdecals <= i)
10407 decalsystem->numdecals = i + 1;
10409 // initialize the decal
10411 decal->triangleindex = triangleindex;
10412 decal->surfaceindex = surfaceindex;
10413 decal->decalsequence = decalsequence;
10414 decal->color4f[0][0] = c0[0];
10415 decal->color4f[0][1] = c0[1];
10416 decal->color4f[0][2] = c0[2];
10417 decal->color4f[0][3] = 1;
10418 decal->color4f[1][0] = c1[0];
10419 decal->color4f[1][1] = c1[1];
10420 decal->color4f[1][2] = c1[2];
10421 decal->color4f[1][3] = 1;
10422 decal->color4f[2][0] = c2[0];
10423 decal->color4f[2][1] = c2[1];
10424 decal->color4f[2][2] = c2[2];
10425 decal->color4f[2][3] = 1;
10426 decal->vertex3f[0][0] = v0[0];
10427 decal->vertex3f[0][1] = v0[1];
10428 decal->vertex3f[0][2] = v0[2];
10429 decal->vertex3f[1][0] = v1[0];
10430 decal->vertex3f[1][1] = v1[1];
10431 decal->vertex3f[1][2] = v1[2];
10432 decal->vertex3f[2][0] = v2[0];
10433 decal->vertex3f[2][1] = v2[1];
10434 decal->vertex3f[2][2] = v2[2];
10435 decal->texcoord2f[0][0] = t0[0];
10436 decal->texcoord2f[0][1] = t0[1];
10437 decal->texcoord2f[1][0] = t1[0];
10438 decal->texcoord2f[1][1] = t1[1];
10439 decal->texcoord2f[2][0] = t2[0];
10440 decal->texcoord2f[2][1] = t2[1];
10441 TriangleNormal(v0, v1, v2, decal->plane);
10442 VectorNormalize(decal->plane);
10443 decal->plane[3] = DotProduct(v0, decal->plane);
10446 extern cvar_t cl_decals_bias;
10447 extern cvar_t cl_decals_models;
10448 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10449 // baseparms, parms, temps
10450 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)
10455 const float *vertex3f;
10456 const float *normal3f;
10458 float points[2][9][3];
10465 e = rsurface.modelelement3i + 3*triangleindex;
10467 vertex3f = rsurface.modelvertex3f;
10468 normal3f = rsurface.modelnormal3f;
10472 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10474 index = 3*e[cornerindex];
10475 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10480 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10482 index = 3*e[cornerindex];
10483 VectorCopy(vertex3f + index, v[cornerindex]);
10488 //TriangleNormal(v[0], v[1], v[2], normal);
10489 //if (DotProduct(normal, localnormal) < 0.0f)
10491 // clip by each of the box planes formed from the projection matrix
10492 // if anything survives, we emit the decal
10493 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]);
10496 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]);
10499 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]);
10502 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]);
10505 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]);
10508 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]);
10511 // some part of the triangle survived, so we have to accept it...
10514 // dynamic always uses the original triangle
10516 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10518 index = 3*e[cornerindex];
10519 VectorCopy(vertex3f + index, v[cornerindex]);
10522 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10524 // convert vertex positions to texcoords
10525 Matrix4x4_Transform(projection, v[cornerindex], temp);
10526 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10527 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10528 // calculate distance fade from the projection origin
10529 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10530 f = bound(0.0f, f, 1.0f);
10531 c[cornerindex][0] = r * f;
10532 c[cornerindex][1] = g * f;
10533 c[cornerindex][2] = b * f;
10534 c[cornerindex][3] = 1.0f;
10535 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10538 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);
10540 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10541 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);
10543 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)
10545 matrix4x4_t projection;
10546 decalsystem_t *decalsystem;
10549 const msurface_t *surface;
10550 const msurface_t *surfaces;
10551 const int *surfacelist;
10552 const texture_t *texture;
10554 int numsurfacelist;
10555 int surfacelistindex;
10558 float localorigin[3];
10559 float localnormal[3];
10560 float localmins[3];
10561 float localmaxs[3];
10564 float planes[6][4];
10567 int bih_triangles_count;
10568 int bih_triangles[256];
10569 int bih_surfaces[256];
10571 decalsystem = &ent->decalsystem;
10572 model = ent->model;
10573 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10575 R_DecalSystem_Reset(&ent->decalsystem);
10579 if (!model->brush.data_leafs && !cl_decals_models.integer)
10581 if (decalsystem->model)
10582 R_DecalSystem_Reset(decalsystem);
10586 if (decalsystem->model != model)
10587 R_DecalSystem_Reset(decalsystem);
10588 decalsystem->model = model;
10590 RSurf_ActiveModelEntity(ent, true, false, false);
10592 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10593 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10594 VectorNormalize(localnormal);
10595 localsize = worldsize*rsurface.inversematrixscale;
10596 localmins[0] = localorigin[0] - localsize;
10597 localmins[1] = localorigin[1] - localsize;
10598 localmins[2] = localorigin[2] - localsize;
10599 localmaxs[0] = localorigin[0] + localsize;
10600 localmaxs[1] = localorigin[1] + localsize;
10601 localmaxs[2] = localorigin[2] + localsize;
10603 //VectorCopy(localnormal, planes[4]);
10604 //VectorVectors(planes[4], planes[2], planes[0]);
10605 AnglesFromVectors(angles, localnormal, NULL, false);
10606 AngleVectors(angles, planes[0], planes[2], planes[4]);
10607 VectorNegate(planes[0], planes[1]);
10608 VectorNegate(planes[2], planes[3]);
10609 VectorNegate(planes[4], planes[5]);
10610 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10611 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10612 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10613 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10614 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10615 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10620 matrix4x4_t forwardprojection;
10621 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10622 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10627 float projectionvector[4][3];
10628 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10629 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10630 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10631 projectionvector[0][0] = planes[0][0] * ilocalsize;
10632 projectionvector[0][1] = planes[1][0] * ilocalsize;
10633 projectionvector[0][2] = planes[2][0] * ilocalsize;
10634 projectionvector[1][0] = planes[0][1] * ilocalsize;
10635 projectionvector[1][1] = planes[1][1] * ilocalsize;
10636 projectionvector[1][2] = planes[2][1] * ilocalsize;
10637 projectionvector[2][0] = planes[0][2] * ilocalsize;
10638 projectionvector[2][1] = planes[1][2] * ilocalsize;
10639 projectionvector[2][2] = planes[2][2] * ilocalsize;
10640 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10641 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10642 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10643 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10647 dynamic = model->surfmesh.isanimated;
10648 numsurfacelist = model->nummodelsurfaces;
10649 surfacelist = model->sortedmodelsurfaces;
10650 surfaces = model->data_surfaces;
10653 bih_triangles_count = -1;
10656 if(model->render_bih.numleafs)
10657 bih = &model->render_bih;
10658 else if(model->collision_bih.numleafs)
10659 bih = &model->collision_bih;
10662 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10663 if(bih_triangles_count == 0)
10665 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10667 if(bih_triangles_count > 0)
10669 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10671 surfaceindex = bih_surfaces[triangleindex];
10672 surface = surfaces + surfaceindex;
10673 texture = surface->texture;
10674 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10676 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10678 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10683 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10685 surfaceindex = surfacelist[surfacelistindex];
10686 surface = surfaces + surfaceindex;
10687 // check cull box first because it rejects more than any other check
10688 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10690 // skip transparent surfaces
10691 texture = surface->texture;
10692 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10694 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10696 numtriangles = surface->num_triangles;
10697 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10698 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10703 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10704 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)
10706 int renderentityindex;
10707 float worldmins[3];
10708 float worldmaxs[3];
10709 entity_render_t *ent;
10711 if (!cl_decals_newsystem.integer)
10714 worldmins[0] = worldorigin[0] - worldsize;
10715 worldmins[1] = worldorigin[1] - worldsize;
10716 worldmins[2] = worldorigin[2] - worldsize;
10717 worldmaxs[0] = worldorigin[0] + worldsize;
10718 worldmaxs[1] = worldorigin[1] + worldsize;
10719 worldmaxs[2] = worldorigin[2] + worldsize;
10721 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10723 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10725 ent = r_refdef.scene.entities[renderentityindex];
10726 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10729 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10733 typedef struct r_decalsystem_splatqueue_s
10735 vec3_t worldorigin;
10736 vec3_t worldnormal;
10742 r_decalsystem_splatqueue_t;
10744 int r_decalsystem_numqueued = 0;
10745 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10747 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)
10749 r_decalsystem_splatqueue_t *queue;
10751 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10754 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10755 VectorCopy(worldorigin, queue->worldorigin);
10756 VectorCopy(worldnormal, queue->worldnormal);
10757 Vector4Set(queue->color, r, g, b, a);
10758 Vector4Set(queue->tcrange, s1, t1, s2, t2);
10759 queue->worldsize = worldsize;
10760 queue->decalsequence = cl.decalsequence++;
10763 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10766 r_decalsystem_splatqueue_t *queue;
10768 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10769 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);
10770 r_decalsystem_numqueued = 0;
10773 extern cvar_t cl_decals_max;
10774 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10777 decalsystem_t *decalsystem = &ent->decalsystem;
10784 if (!decalsystem->numdecals)
10787 if (r_showsurfaces.integer)
10790 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10792 R_DecalSystem_Reset(decalsystem);
10796 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10797 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10799 if (decalsystem->lastupdatetime)
10800 frametime = (cl.time - decalsystem->lastupdatetime);
10803 decalsystem->lastupdatetime = cl.time;
10804 decal = decalsystem->decals;
10805 numdecals = decalsystem->numdecals;
10807 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10809 if (decal->color4f[0][3])
10811 decal->lived += frametime;
10812 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10814 memset(decal, 0, sizeof(*decal));
10815 if (decalsystem->freedecal > i)
10816 decalsystem->freedecal = i;
10820 decal = decalsystem->decals;
10821 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10824 // collapse the array by shuffling the tail decals into the gaps
10827 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10828 decalsystem->freedecal++;
10829 if (decalsystem->freedecal == numdecals)
10831 decal[decalsystem->freedecal] = decal[--numdecals];
10834 decalsystem->numdecals = numdecals;
10836 if (numdecals <= 0)
10838 // if there are no decals left, reset decalsystem
10839 R_DecalSystem_Reset(decalsystem);
10843 extern skinframe_t *decalskinframe;
10844 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10847 decalsystem_t *decalsystem = &ent->decalsystem;
10856 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10859 numdecals = decalsystem->numdecals;
10863 if (r_showsurfaces.integer)
10866 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10868 R_DecalSystem_Reset(decalsystem);
10872 // if the model is static it doesn't matter what value we give for
10873 // wantnormals and wanttangents, so this logic uses only rules applicable
10874 // to a model, knowing that they are meaningless otherwise
10875 if (ent == r_refdef.scene.worldentity)
10876 RSurf_ActiveWorldEntity();
10878 RSurf_ActiveModelEntity(ent, false, false, false);
10880 decalsystem->lastupdatetime = cl.time;
10881 decal = decalsystem->decals;
10883 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10885 // update vertex positions for animated models
10886 v3f = decalsystem->vertex3f;
10887 c4f = decalsystem->color4f;
10888 t2f = decalsystem->texcoord2f;
10889 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10891 if (!decal->color4f[0][3])
10894 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10898 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
10901 // update color values for fading decals
10902 if (decal->lived >= cl_decals_time.value)
10903 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10907 c4f[ 0] = decal->color4f[0][0] * alpha;
10908 c4f[ 1] = decal->color4f[0][1] * alpha;
10909 c4f[ 2] = decal->color4f[0][2] * alpha;
10911 c4f[ 4] = decal->color4f[1][0] * alpha;
10912 c4f[ 5] = decal->color4f[1][1] * alpha;
10913 c4f[ 6] = decal->color4f[1][2] * alpha;
10915 c4f[ 8] = decal->color4f[2][0] * alpha;
10916 c4f[ 9] = decal->color4f[2][1] * alpha;
10917 c4f[10] = decal->color4f[2][2] * alpha;
10920 t2f[0] = decal->texcoord2f[0][0];
10921 t2f[1] = decal->texcoord2f[0][1];
10922 t2f[2] = decal->texcoord2f[1][0];
10923 t2f[3] = decal->texcoord2f[1][1];
10924 t2f[4] = decal->texcoord2f[2][0];
10925 t2f[5] = decal->texcoord2f[2][1];
10927 // update vertex positions for animated models
10928 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10930 e = rsurface.modelelement3i + 3*decal->triangleindex;
10931 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10932 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10933 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10937 VectorCopy(decal->vertex3f[0], v3f);
10938 VectorCopy(decal->vertex3f[1], v3f + 3);
10939 VectorCopy(decal->vertex3f[2], v3f + 6);
10942 if (r_refdef.fogenabled)
10944 alpha = RSurf_FogVertex(v3f);
10945 VectorScale(c4f, alpha, c4f);
10946 alpha = RSurf_FogVertex(v3f + 3);
10947 VectorScale(c4f + 4, alpha, c4f + 4);
10948 alpha = RSurf_FogVertex(v3f + 6);
10949 VectorScale(c4f + 8, alpha, c4f + 8);
10960 r_refdef.stats.drawndecals += numtris;
10962 // now render the decals all at once
10963 // (this assumes they all use one particle font texture!)
10964 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);
10965 // R_Mesh_ResetTextureState();
10966 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10967 GL_DepthMask(false);
10968 GL_DepthRange(0, 1);
10969 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10970 GL_DepthTest(true);
10971 GL_CullFace(GL_NONE);
10972 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10973 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10974 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10978 static void R_DrawModelDecals(void)
10982 // fade faster when there are too many decals
10983 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10984 for (i = 0;i < r_refdef.scene.numentities;i++)
10985 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10987 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10988 for (i = 0;i < r_refdef.scene.numentities;i++)
10989 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10990 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10992 R_DecalSystem_ApplySplatEntitiesQueue();
10994 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10995 for (i = 0;i < r_refdef.scene.numentities;i++)
10996 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10998 r_refdef.stats.totaldecals += numdecals;
11000 if (r_showsurfaces.integer)
11003 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11005 for (i = 0;i < r_refdef.scene.numentities;i++)
11007 if (!r_refdef.viewcache.entityvisible[i])
11009 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11010 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11014 extern cvar_t mod_collision_bih;
11015 void R_DrawDebugModel(void)
11017 entity_render_t *ent = rsurface.entity;
11018 int i, j, k, l, flagsmask;
11019 const msurface_t *surface;
11020 dp_model_t *model = ent->model;
11023 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11026 if (r_showoverdraw.value > 0)
11028 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11029 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11030 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11031 GL_DepthTest(false);
11032 GL_DepthMask(false);
11033 GL_DepthRange(0, 1);
11034 GL_BlendFunc(GL_ONE, GL_ONE);
11035 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11037 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11039 rsurface.texture = R_GetCurrentTexture(surface->texture);
11040 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11042 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11043 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11044 if (!rsurface.texture->currentlayers->depthmask)
11045 GL_Color(c, 0, 0, 1.0f);
11046 else if (ent == r_refdef.scene.worldentity)
11047 GL_Color(c, c, c, 1.0f);
11049 GL_Color(0, c, 0, 1.0f);
11050 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11054 rsurface.texture = NULL;
11057 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11059 // R_Mesh_ResetTextureState();
11060 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11061 GL_DepthRange(0, 1);
11062 GL_DepthTest(!r_showdisabledepthtest.integer);
11063 GL_DepthMask(false);
11064 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11066 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11070 qboolean cullbox = ent == r_refdef.scene.worldentity;
11071 const q3mbrush_t *brush;
11072 const bih_t *bih = &model->collision_bih;
11073 const bih_leaf_t *bihleaf;
11074 float vertex3f[3][3];
11075 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11077 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11079 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11081 switch (bihleaf->type)
11084 brush = model->brush.data_brushes + bihleaf->itemindex;
11085 if (brush->colbrushf && brush->colbrushf->numtriangles)
11087 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);
11088 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11089 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11092 case BIH_COLLISIONTRIANGLE:
11093 triangleindex = bihleaf->itemindex;
11094 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11095 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11096 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11097 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);
11098 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11099 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11101 case BIH_RENDERTRIANGLE:
11102 triangleindex = bihleaf->itemindex;
11103 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11104 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11105 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11106 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);
11107 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11108 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11114 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11116 if (r_showtris.integer && qglPolygonMode)
11118 if (r_showdisabledepthtest.integer)
11120 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11121 GL_DepthMask(false);
11125 GL_BlendFunc(GL_ONE, GL_ZERO);
11126 GL_DepthMask(true);
11128 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11129 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11131 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11133 rsurface.texture = R_GetCurrentTexture(surface->texture);
11134 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11136 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11137 if (!rsurface.texture->currentlayers->depthmask)
11138 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11139 else if (ent == r_refdef.scene.worldentity)
11140 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11142 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11143 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11147 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11148 rsurface.texture = NULL;
11151 if (r_shownormals.value != 0 && qglBegin)
11153 if (r_showdisabledepthtest.integer)
11155 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11156 GL_DepthMask(false);
11160 GL_BlendFunc(GL_ONE, GL_ZERO);
11161 GL_DepthMask(true);
11163 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11165 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11167 rsurface.texture = R_GetCurrentTexture(surface->texture);
11168 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11170 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11171 qglBegin(GL_LINES);
11172 if (r_shownormals.value < 0)
11174 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11176 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11177 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11178 qglVertex3f(v[0], v[1], v[2]);
11179 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11180 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11181 qglVertex3f(v[0], v[1], v[2]);
11184 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11186 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11188 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11189 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11190 qglVertex3f(v[0], v[1], v[2]);
11191 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11192 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11193 qglVertex3f(v[0], v[1], v[2]);
11195 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11197 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11198 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11199 qglVertex3f(v[0], v[1], v[2]);
11200 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11201 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11202 qglVertex3f(v[0], v[1], v[2]);
11204 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11206 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11207 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11208 qglVertex3f(v[0], v[1], v[2]);
11209 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11210 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11211 qglVertex3f(v[0], v[1], v[2]);
11218 rsurface.texture = NULL;
11222 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11223 int r_maxsurfacelist = 0;
11224 const msurface_t **r_surfacelist = NULL;
11225 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11227 int i, j, endj, flagsmask;
11228 dp_model_t *model = r_refdef.scene.worldmodel;
11229 msurface_t *surfaces;
11230 unsigned char *update;
11231 int numsurfacelist = 0;
11235 if (r_maxsurfacelist < model->num_surfaces)
11237 r_maxsurfacelist = model->num_surfaces;
11239 Mem_Free((msurface_t**)r_surfacelist);
11240 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11243 RSurf_ActiveWorldEntity();
11245 surfaces = model->data_surfaces;
11246 update = model->brushq1.lightmapupdateflags;
11248 // update light styles on this submodel
11249 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11251 model_brush_lightstyleinfo_t *style;
11252 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11254 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11256 int *list = style->surfacelist;
11257 style->value = r_refdef.scene.lightstylevalue[style->style];
11258 for (j = 0;j < style->numsurfaces;j++)
11259 update[list[j]] = true;
11264 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11268 R_DrawDebugModel();
11269 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11273 rsurface.lightmaptexture = NULL;
11274 rsurface.deluxemaptexture = NULL;
11275 rsurface.uselightmaptexture = false;
11276 rsurface.texture = NULL;
11277 rsurface.rtlight = NULL;
11278 numsurfacelist = 0;
11279 // add visible surfaces to draw list
11280 for (i = 0;i < model->nummodelsurfaces;i++)
11282 j = model->sortedmodelsurfaces[i];
11283 if (r_refdef.viewcache.world_surfacevisible[j])
11284 r_surfacelist[numsurfacelist++] = surfaces + j;
11286 // update lightmaps if needed
11287 if (model->brushq1.firstrender)
11289 model->brushq1.firstrender = false;
11290 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11292 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11296 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11297 if (r_refdef.viewcache.world_surfacevisible[j])
11299 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11301 // don't do anything if there were no surfaces
11302 if (!numsurfacelist)
11304 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11307 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11309 // add to stats if desired
11310 if (r_speeds.integer && !skysurfaces && !depthonly)
11312 r_refdef.stats.world_surfaces += numsurfacelist;
11313 for (j = 0;j < numsurfacelist;j++)
11314 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11317 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11320 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11322 int i, j, endj, flagsmask;
11323 dp_model_t *model = ent->model;
11324 msurface_t *surfaces;
11325 unsigned char *update;
11326 int numsurfacelist = 0;
11330 if (r_maxsurfacelist < model->num_surfaces)
11332 r_maxsurfacelist = model->num_surfaces;
11334 Mem_Free((msurface_t **)r_surfacelist);
11335 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11338 // if the model is static it doesn't matter what value we give for
11339 // wantnormals and wanttangents, so this logic uses only rules applicable
11340 // to a model, knowing that they are meaningless otherwise
11341 if (ent == r_refdef.scene.worldentity)
11342 RSurf_ActiveWorldEntity();
11343 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11344 RSurf_ActiveModelEntity(ent, false, false, false);
11346 RSurf_ActiveModelEntity(ent, true, true, true);
11347 else if (depthonly)
11349 switch (vid.renderpath)
11351 case RENDERPATH_GL20:
11352 case RENDERPATH_D3D9:
11353 case RENDERPATH_D3D10:
11354 case RENDERPATH_D3D11:
11355 case RENDERPATH_SOFT:
11356 case RENDERPATH_GLES2:
11357 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11359 case RENDERPATH_GL11:
11360 case RENDERPATH_GL13:
11361 case RENDERPATH_GLES1:
11362 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11368 switch (vid.renderpath)
11370 case RENDERPATH_GL20:
11371 case RENDERPATH_D3D9:
11372 case RENDERPATH_D3D10:
11373 case RENDERPATH_D3D11:
11374 case RENDERPATH_SOFT:
11375 case RENDERPATH_GLES2:
11376 RSurf_ActiveModelEntity(ent, true, true, false);
11378 case RENDERPATH_GL11:
11379 case RENDERPATH_GL13:
11380 case RENDERPATH_GLES1:
11381 RSurf_ActiveModelEntity(ent, true, false, false);
11386 surfaces = model->data_surfaces;
11387 update = model->brushq1.lightmapupdateflags;
11389 // update light styles
11390 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11392 model_brush_lightstyleinfo_t *style;
11393 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11395 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11397 int *list = style->surfacelist;
11398 style->value = r_refdef.scene.lightstylevalue[style->style];
11399 for (j = 0;j < style->numsurfaces;j++)
11400 update[list[j]] = true;
11405 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11409 R_DrawDebugModel();
11410 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11414 rsurface.lightmaptexture = NULL;
11415 rsurface.deluxemaptexture = NULL;
11416 rsurface.uselightmaptexture = false;
11417 rsurface.texture = NULL;
11418 rsurface.rtlight = NULL;
11419 numsurfacelist = 0;
11420 // add visible surfaces to draw list
11421 for (i = 0;i < model->nummodelsurfaces;i++)
11422 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11423 // don't do anything if there were no surfaces
11424 if (!numsurfacelist)
11426 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11429 // update lightmaps if needed
11433 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11438 R_BuildLightMap(ent, surfaces + j);
11443 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11445 R_BuildLightMap(ent, surfaces + j);
11446 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11448 // add to stats if desired
11449 if (r_speeds.integer && !skysurfaces && !depthonly)
11451 r_refdef.stats.entities_surfaces += numsurfacelist;
11452 for (j = 0;j < numsurfacelist;j++)
11453 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11456 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11459 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11461 static texture_t texture;
11462 static msurface_t surface;
11463 const msurface_t *surfacelist = &surface;
11465 // fake enough texture and surface state to render this geometry
11467 texture.update_lastrenderframe = -1; // regenerate this texture
11468 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11469 texture.currentskinframe = skinframe;
11470 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11471 texture.offsetmapping = OFFSETMAPPING_OFF;
11472 texture.offsetscale = 1;
11473 texture.specularscalemod = 1;
11474 texture.specularpowermod = 1;
11476 surface.texture = &texture;
11477 surface.num_triangles = numtriangles;
11478 surface.num_firsttriangle = firsttriangle;
11479 surface.num_vertices = numvertices;
11480 surface.num_firstvertex = firstvertex;
11483 rsurface.texture = R_GetCurrentTexture(surface.texture);
11484 rsurface.lightmaptexture = NULL;
11485 rsurface.deluxemaptexture = NULL;
11486 rsurface.uselightmaptexture = false;
11487 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11490 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)
11492 static msurface_t surface;
11493 const msurface_t *surfacelist = &surface;
11495 // fake enough texture and surface state to render this geometry
11496 surface.texture = texture;
11497 surface.num_triangles = numtriangles;
11498 surface.num_firsttriangle = firsttriangle;
11499 surface.num_vertices = numvertices;
11500 surface.num_firstvertex = firstvertex;
11503 rsurface.texture = R_GetCurrentTexture(surface.texture);
11504 rsurface.lightmaptexture = NULL;
11505 rsurface.deluxemaptexture = NULL;
11506 rsurface.uselightmaptexture = false;
11507 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);