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", "screen motionblur - value represents intensity, somewhere around 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended"};
55 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
56 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
57 cvar_t r_motionblur_minblur = {CVAR_SAVE, "r_motionblur_minblur", "0.5", "factor of blur to apply at all times (always have this amount of blur no matter what the other factors are)"};
58 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
59 cvar_t r_motionblur_velocityfactor = {CVAR_SAVE, "r_motionblur_velocityfactor", "1", "factoring in of player velocity to the blur equation - the faster the player moves around the map, the more blur they get"};
60 cvar_t r_motionblur_velocityfactor_minspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_minspeed", "400", "lower value of velocity when it starts to factor into blur equation"};
61 cvar_t r_motionblur_velocityfactor_maxspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_maxspeed", "800", "upper value of velocity when it reaches the peak factor into blur equation"};
62 cvar_t r_motionblur_mousefactor = {CVAR_SAVE, "r_motionblur_mousefactor", "2", "factoring in of mouse acceleration to the blur equation - the faster the player turns their mouse, the more blur they get"};
63 cvar_t r_motionblur_mousefactor_minspeed = {CVAR_SAVE, "r_motionblur_mousefactor_minspeed", "0", "lower value of mouse acceleration when it starts to factor into blur equation"};
64 cvar_t r_motionblur_mousefactor_maxspeed = {CVAR_SAVE, "r_motionblur_mousefactor_maxspeed", "50", "upper value of mouse acceleration when it reaches the peak factor into blur equation"};
66 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
67 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"};
68 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
69 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)"};
70 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
72 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"};
73 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
74 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
75 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
76 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
77 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
78 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
79 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "1", "enables GL_ALPHA_TO_COVERAGE antialiasing technique on alphablend and alphatest surfaces when using vid_samples 2 or higher"};
80 cvar_t r_transparent_sortsurfacesbynearest = {0, "r_transparent_sortsurfacesbynearest", "1", "sort entity and world surfaces by nearest point on bounding box instead of using the center of the bounding box, usually reduces sorting artifacts"};
81 cvar_t r_transparent_useplanardistance = {0, "r_transparent_useplanardistance", "0", "sort transparent meshes by distance from view plane rather than spherical distance to the chosen point"};
82 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
83 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
84 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)"};
85 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
86 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
87 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"};
88 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"};
89 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
90 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"};
91 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"};
92 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"};
93 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
94 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
95 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
96 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
97 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
98 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
99 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
100 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)"};
101 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)"};
102 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
103 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
104 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
105 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
106 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
108 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
109 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
110 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
112 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
113 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
114 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
115 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."};
116 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
117 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
118 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
119 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."};
120 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
121 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
122 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
123 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
124 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"};
125 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"};
126 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
127 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
128 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
129 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
130 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
131 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"};
132 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
133 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
134 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
136 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
137 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
138 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
139 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
140 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
141 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
142 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
143 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
145 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)"};
146 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"};
148 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
149 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
150 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
152 cvar_t r_usedepthtextures = {CVAR_SAVE, "r_usedepthtextures", "1", "use depth texture instead of depth renderbuffer where possible, uses less video memory but may render slower (or faster) depending on hardware"};
153 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"};
154 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"};
155 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
156 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
157 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"};
158 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)"};
159 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)"};
160 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
162 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)"};
163 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
164 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)"};
165 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
166 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)"};
167 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)"};
168 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
169 cvar_t r_glsl_offsetmapping_lod = {CVAR_SAVE, "r_glsl_offsetmapping_lod", "0", "apply distance-based level-of-detail correction to number of offsetmappig steps, effectively making it render faster on large open-area maps"};
170 cvar_t r_glsl_offsetmapping_lod_distance = {CVAR_SAVE, "r_glsl_offsetmapping_lod_distance", "32", "first LOD level distance, second level (-50% steps) is 2x of this, third (33%) - 3x etc."};
171 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
172 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)"};
173 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)"};
174 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)"};
175 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)"};
176 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)"};
177 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)"};
178 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)"};
179 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)"};
181 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)"};
182 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
183 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"};
184 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
185 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
186 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
187 cvar_t r_water_lowquality = {0, "r_water_lowquality", "0", "special option to accelerate water rendering, 1 disables shadows and particles, 2 disables all dynamic lights"};
188 cvar_t r_water_hideplayer = {CVAR_SAVE, "r_water_hideplayer", "0", "if set to 1 then player will be hidden in refraction views, if set to 2 then player will also be hidden in reflection views, player is always visible in camera views"};
189 cvar_t r_water_fbo = {CVAR_SAVE, "r_water_fbo", "1", "enables use of render to texture for water effects, otherwise copy to texture is used (slower)"};
191 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
192 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
193 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
194 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
196 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
197 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
199 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
200 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
201 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
202 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
203 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
205 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
206 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
207 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
208 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
209 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
210 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
211 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
212 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
213 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
214 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
216 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"};
218 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"};
220 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
222 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
224 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
225 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"};
227 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."};
229 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)"};
231 extern cvar_t v_glslgamma;
232 extern cvar_t v_glslgamma_2d;
234 extern qboolean v_flipped_state;
236 r_framebufferstate_t r_fb;
238 /// shadow volume bsp struct with automatically growing nodes buffer
241 rtexture_t *r_texture_blanknormalmap;
242 rtexture_t *r_texture_white;
243 rtexture_t *r_texture_grey128;
244 rtexture_t *r_texture_black;
245 rtexture_t *r_texture_notexture;
246 rtexture_t *r_texture_whitecube;
247 rtexture_t *r_texture_normalizationcube;
248 rtexture_t *r_texture_fogattenuation;
249 rtexture_t *r_texture_fogheighttexture;
250 rtexture_t *r_texture_gammaramps;
251 unsigned int r_texture_gammaramps_serial;
252 //rtexture_t *r_texture_fogintensity;
253 rtexture_t *r_texture_reflectcube;
255 // TODO: hash lookups?
256 typedef struct cubemapinfo_s
263 int r_texture_numcubemaps;
264 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
266 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
267 unsigned int r_numqueries;
268 unsigned int r_maxqueries;
270 typedef struct r_qwskincache_s
272 char name[MAX_QPATH];
273 skinframe_t *skinframe;
277 static r_qwskincache_t *r_qwskincache;
278 static int r_qwskincache_size;
280 /// vertex coordinates for a quad that covers the screen exactly
281 extern const float r_screenvertex3f[12];
282 extern const float r_d3dscreenvertex3f[12];
283 const float r_screenvertex3f[12] =
290 const float r_d3dscreenvertex3f[12] =
298 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
301 for (i = 0;i < verts;i++)
312 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
315 for (i = 0;i < verts;i++)
325 // FIXME: move this to client?
328 if (gamemode == GAME_NEHAHRA)
330 Cvar_Set("gl_fogenable", "0");
331 Cvar_Set("gl_fogdensity", "0.2");
332 Cvar_Set("gl_fogred", "0.3");
333 Cvar_Set("gl_foggreen", "0.3");
334 Cvar_Set("gl_fogblue", "0.3");
336 r_refdef.fog_density = 0;
337 r_refdef.fog_red = 0;
338 r_refdef.fog_green = 0;
339 r_refdef.fog_blue = 0;
340 r_refdef.fog_alpha = 1;
341 r_refdef.fog_start = 0;
342 r_refdef.fog_end = 16384;
343 r_refdef.fog_height = 1<<30;
344 r_refdef.fog_fadedepth = 128;
345 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
348 static void R_BuildBlankTextures(void)
350 unsigned char data[4];
351 data[2] = 128; // normal X
352 data[1] = 128; // normal Y
353 data[0] = 255; // normal Z
354 data[3] = 255; // height
355 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
360 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
365 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
370 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
373 static void R_BuildNoTexture(void)
376 unsigned char pix[16][16][4];
377 // this makes a light grey/dark grey checkerboard texture
378 for (y = 0;y < 16;y++)
380 for (x = 0;x < 16;x++)
382 if ((y < 8) ^ (x < 8))
398 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
401 static void R_BuildWhiteCube(void)
403 unsigned char data[6*1*1*4];
404 memset(data, 255, sizeof(data));
405 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
408 static void R_BuildNormalizationCube(void)
412 vec_t s, t, intensity;
415 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
416 for (side = 0;side < 6;side++)
418 for (y = 0;y < NORMSIZE;y++)
420 for (x = 0;x < NORMSIZE;x++)
422 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
423 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
458 intensity = 127.0f / sqrt(DotProduct(v, v));
459 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
460 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
461 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
462 data[((side*64+y)*64+x)*4+3] = 255;
466 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
470 static void R_BuildFogTexture(void)
474 unsigned char data1[FOGWIDTH][4];
475 //unsigned char data2[FOGWIDTH][4];
478 r_refdef.fogmasktable_start = r_refdef.fog_start;
479 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
480 r_refdef.fogmasktable_range = r_refdef.fogrange;
481 r_refdef.fogmasktable_density = r_refdef.fog_density;
483 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
484 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
486 d = (x * r - r_refdef.fogmasktable_start);
487 if(developer_extra.integer)
488 Con_DPrintf("%f ", d);
490 if (r_fog_exp2.integer)
491 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
493 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
494 if(developer_extra.integer)
495 Con_DPrintf(" : %f ", alpha);
496 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
497 if(developer_extra.integer)
498 Con_DPrintf(" = %f\n", alpha);
499 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
502 for (x = 0;x < FOGWIDTH;x++)
504 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
509 //data2[x][0] = 255 - b;
510 //data2[x][1] = 255 - b;
511 //data2[x][2] = 255 - b;
514 if (r_texture_fogattenuation)
516 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
517 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
521 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
522 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
526 static void R_BuildFogHeightTexture(void)
528 unsigned char *inpixels;
536 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
537 if (r_refdef.fogheighttexturename[0])
538 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
541 r_refdef.fog_height_tablesize = 0;
542 if (r_texture_fogheighttexture)
543 R_FreeTexture(r_texture_fogheighttexture);
544 r_texture_fogheighttexture = NULL;
545 if (r_refdef.fog_height_table2d)
546 Mem_Free(r_refdef.fog_height_table2d);
547 r_refdef.fog_height_table2d = NULL;
548 if (r_refdef.fog_height_table1d)
549 Mem_Free(r_refdef.fog_height_table1d);
550 r_refdef.fog_height_table1d = NULL;
554 r_refdef.fog_height_tablesize = size;
555 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
556 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
557 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
559 // LordHavoc: now the magic - what is that table2d for? it is a cooked
560 // average fog color table accounting for every fog layer between a point
561 // and the camera. (Note: attenuation is handled separately!)
562 for (y = 0;y < size;y++)
564 for (x = 0;x < size;x++)
570 for (j = x;j <= y;j++)
572 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
578 for (j = x;j >= y;j--)
580 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
585 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
586 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
587 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
588 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
591 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
594 //=======================================================================================================================================================
596 static const char *builtinshaderstring =
597 #include "shader_glsl.h"
600 const char *builtinhlslshaderstring =
601 #include "shader_hlsl.h"
604 char *glslshaderstring = NULL;
605 char *hlslshaderstring = NULL;
607 //=======================================================================================================================================================
609 typedef struct shaderpermutationinfo_s
614 shaderpermutationinfo_t;
616 typedef struct shadermodeinfo_s
618 const char *vertexfilename;
619 const char *geometryfilename;
620 const char *fragmentfilename;
626 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
627 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
629 {"#define USEDIFFUSE\n", " diffuse"},
630 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
631 {"#define USEVIEWTINT\n", " viewtint"},
632 {"#define USECOLORMAPPING\n", " colormapping"},
633 {"#define USESATURATION\n", " saturation"},
634 {"#define USEFOGINSIDE\n", " foginside"},
635 {"#define USEFOGOUTSIDE\n", " fogoutside"},
636 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
637 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
638 {"#define USEGAMMARAMPS\n", " gammaramps"},
639 {"#define USECUBEFILTER\n", " cubefilter"},
640 {"#define USEGLOW\n", " glow"},
641 {"#define USEBLOOM\n", " bloom"},
642 {"#define USESPECULAR\n", " specular"},
643 {"#define USEPOSTPROCESSING\n", " postprocessing"},
644 {"#define USEREFLECTION\n", " reflection"},
645 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
646 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
647 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
648 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
649 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
650 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
651 {"#define USEALPHAKILL\n", " alphakill"},
652 {"#define USEREFLECTCUBE\n", " reflectcube"},
653 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
654 {"#define USEBOUNCEGRID\n", " bouncegrid"},
655 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
656 {"#define USETRIPPY\n", " trippy"},
657 {"#define USEDEPTHRGB\n", " depthrgb"},
660 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
661 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
663 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
664 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
665 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
666 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
667 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
668 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
669 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
670 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
671 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
672 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
673 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
674 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
675 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
676 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
677 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
678 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
679 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
680 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
683 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
685 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
686 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
687 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
688 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
689 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
690 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
691 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
692 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
693 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
694 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
695 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
696 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
697 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
698 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
699 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
700 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
701 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
702 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
705 struct r_glsl_permutation_s;
706 typedef struct r_glsl_permutation_s
709 struct r_glsl_permutation_s *hashnext;
711 unsigned int permutation;
713 /// indicates if we have tried compiling this permutation already
715 /// 0 if compilation failed
717 // texture units assigned to each detected uniform
718 int tex_Texture_First;
719 int tex_Texture_Second;
720 int tex_Texture_GammaRamps;
721 int tex_Texture_Normal;
722 int tex_Texture_Color;
723 int tex_Texture_Gloss;
724 int tex_Texture_Glow;
725 int tex_Texture_SecondaryNormal;
726 int tex_Texture_SecondaryColor;
727 int tex_Texture_SecondaryGloss;
728 int tex_Texture_SecondaryGlow;
729 int tex_Texture_Pants;
730 int tex_Texture_Shirt;
731 int tex_Texture_FogHeightTexture;
732 int tex_Texture_FogMask;
733 int tex_Texture_Lightmap;
734 int tex_Texture_Deluxemap;
735 int tex_Texture_Attenuation;
736 int tex_Texture_Cube;
737 int tex_Texture_Refraction;
738 int tex_Texture_Reflection;
739 int tex_Texture_ShadowMap2D;
740 int tex_Texture_CubeProjection;
741 int tex_Texture_ScreenNormalMap;
742 int tex_Texture_ScreenDiffuse;
743 int tex_Texture_ScreenSpecular;
744 int tex_Texture_ReflectMask;
745 int tex_Texture_ReflectCube;
746 int tex_Texture_BounceGrid;
747 /// locations of detected uniforms in program object, or -1 if not found
748 int loc_Texture_First;
749 int loc_Texture_Second;
750 int loc_Texture_GammaRamps;
751 int loc_Texture_Normal;
752 int loc_Texture_Color;
753 int loc_Texture_Gloss;
754 int loc_Texture_Glow;
755 int loc_Texture_SecondaryNormal;
756 int loc_Texture_SecondaryColor;
757 int loc_Texture_SecondaryGloss;
758 int loc_Texture_SecondaryGlow;
759 int loc_Texture_Pants;
760 int loc_Texture_Shirt;
761 int loc_Texture_FogHeightTexture;
762 int loc_Texture_FogMask;
763 int loc_Texture_Lightmap;
764 int loc_Texture_Deluxemap;
765 int loc_Texture_Attenuation;
766 int loc_Texture_Cube;
767 int loc_Texture_Refraction;
768 int loc_Texture_Reflection;
769 int loc_Texture_ShadowMap2D;
770 int loc_Texture_CubeProjection;
771 int loc_Texture_ScreenNormalMap;
772 int loc_Texture_ScreenDiffuse;
773 int loc_Texture_ScreenSpecular;
774 int loc_Texture_ReflectMask;
775 int loc_Texture_ReflectCube;
776 int loc_Texture_BounceGrid;
778 int loc_BloomBlur_Parameters;
780 int loc_Color_Ambient;
781 int loc_Color_Diffuse;
782 int loc_Color_Specular;
786 int loc_DeferredColor_Ambient;
787 int loc_DeferredColor_Diffuse;
788 int loc_DeferredColor_Specular;
789 int loc_DeferredMod_Diffuse;
790 int loc_DeferredMod_Specular;
791 int loc_DistortScaleRefractReflect;
794 int loc_FogHeightFade;
796 int loc_FogPlaneViewDist;
797 int loc_FogRangeRecip;
800 int loc_LightPosition;
801 int loc_OffsetMapping_ScaleSteps;
802 int loc_OffsetMapping_LodDistance;
803 int loc_OffsetMapping_Bias;
805 int loc_ReflectColor;
806 int loc_ReflectFactor;
807 int loc_ReflectOffset;
808 int loc_RefractColor;
810 int loc_ScreenCenterRefractReflect;
811 int loc_ScreenScaleRefractReflect;
812 int loc_ScreenToDepth;
813 int loc_ShadowMap_Parameters;
814 int loc_ShadowMap_TextureScale;
815 int loc_SpecularPower;
820 int loc_ViewTintColor;
822 int loc_ModelToLight;
824 int loc_BackgroundTexMatrix;
825 int loc_ModelViewProjectionMatrix;
826 int loc_ModelViewMatrix;
827 int loc_PixelToScreenTexCoord;
828 int loc_ModelToReflectCube;
829 int loc_ShadowMapMatrix;
830 int loc_BloomColorSubtract;
831 int loc_NormalmapScrollBlend;
832 int loc_BounceGridMatrix;
833 int loc_BounceGridIntensity;
835 r_glsl_permutation_t;
837 #define SHADERPERMUTATION_HASHSIZE 256
840 // non-degradable "lightweight" shader parameters to keep the permutations simpler
841 // these can NOT degrade! only use for simple stuff
844 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
845 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
846 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
847 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
848 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
849 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
850 SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
851 SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7, ///< LOD for offsetmapping
852 SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
853 SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
854 SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
856 #define SHADERSTATICPARMS_COUNT 11
858 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
859 static int shaderstaticparms_count = 0;
861 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
862 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
864 extern qboolean r_shadow_shadowmapsampler;
865 extern int r_shadow_shadowmappcf;
866 qboolean R_CompileShader_CheckStaticParms(void)
868 static int r_compileshader_staticparms_save[1];
869 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
870 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
873 if (r_glsl_saturation_redcompensate.integer)
874 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
875 if (r_glsl_vertextextureblend_usebothalphas.integer)
876 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
877 if (r_shadow_glossexact.integer)
878 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
879 if (r_glsl_postprocess.integer)
881 if (r_glsl_postprocess_uservec1_enable.integer)
882 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
883 if (r_glsl_postprocess_uservec2_enable.integer)
884 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
885 if (r_glsl_postprocess_uservec3_enable.integer)
886 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
887 if (r_glsl_postprocess_uservec4_enable.integer)
888 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
890 if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
891 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
893 if (r_shadow_shadowmapsampler)
894 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
895 if (r_shadow_shadowmappcf > 1)
896 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
897 else if (r_shadow_shadowmappcf)
898 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
900 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
903 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
904 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
905 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
907 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
908 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
910 shaderstaticparms_count = 0;
913 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
914 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
915 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
916 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
917 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
918 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
919 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
920 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
921 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
922 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
923 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
926 /// information about each possible shader permutation
927 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
928 /// currently selected permutation
929 r_glsl_permutation_t *r_glsl_permutation;
930 /// storage for permutations linked in the hash table
931 memexpandablearray_t r_glsl_permutationarray;
933 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
935 //unsigned int hashdepth = 0;
936 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
937 r_glsl_permutation_t *p;
938 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
940 if (p->mode == mode && p->permutation == permutation)
942 //if (hashdepth > 10)
943 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
948 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
950 p->permutation = permutation;
951 p->hashnext = r_glsl_permutationhash[mode][hashindex];
952 r_glsl_permutationhash[mode][hashindex] = p;
953 //if (hashdepth > 10)
954 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
958 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
961 if (!filename || !filename[0])
963 if (!strcmp(filename, "glsl/default.glsl"))
965 if (!glslshaderstring)
967 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
968 if (glslshaderstring)
969 Con_DPrintf("Loading shaders from file %s...\n", filename);
971 glslshaderstring = (char *)builtinshaderstring;
973 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
974 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
977 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
980 if (printfromdisknotice)
981 Con_DPrintf("from disk %s... ", filename);
987 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
991 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
992 char *vertexstring, *geometrystring, *fragmentstring;
993 char permutationname[256];
994 int vertstrings_count = 0;
995 int geomstrings_count = 0;
996 int fragstrings_count = 0;
997 const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
998 const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
999 const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1006 permutationname[0] = 0;
1007 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1008 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1009 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1011 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1013 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1014 if(vid.support.gl20shaders130)
1016 vertstrings_list[vertstrings_count++] = "#version 130\n";
1017 geomstrings_list[geomstrings_count++] = "#version 130\n";
1018 fragstrings_list[fragstrings_count++] = "#version 130\n";
1019 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1020 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1021 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1024 // the first pretext is which type of shader to compile as
1025 // (later these will all be bound together as a program object)
1026 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1027 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1028 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1030 // the second pretext is the mode (for example a light source)
1031 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1032 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1033 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1034 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1036 // now add all the permutation pretexts
1037 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1039 if (permutation & (1<<i))
1041 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1042 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1043 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1044 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1048 // keep line numbers correct
1049 vertstrings_list[vertstrings_count++] = "\n";
1050 geomstrings_list[geomstrings_count++] = "\n";
1051 fragstrings_list[fragstrings_count++] = "\n";
1056 R_CompileShader_AddStaticParms(mode, permutation);
1057 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1058 vertstrings_count += shaderstaticparms_count;
1059 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1060 geomstrings_count += shaderstaticparms_count;
1061 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1062 fragstrings_count += shaderstaticparms_count;
1064 // now append the shader text itself
1065 vertstrings_list[vertstrings_count++] = vertexstring;
1066 geomstrings_list[geomstrings_count++] = geometrystring;
1067 fragstrings_list[fragstrings_count++] = fragmentstring;
1069 // if any sources were NULL, clear the respective list
1071 vertstrings_count = 0;
1072 if (!geometrystring)
1073 geomstrings_count = 0;
1074 if (!fragmentstring)
1075 fragstrings_count = 0;
1077 // compile the shader program
1078 if (vertstrings_count + geomstrings_count + fragstrings_count)
1079 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1083 qglUseProgram(p->program);CHECKGLERROR
1084 // look up all the uniform variable names we care about, so we don't
1085 // have to look them up every time we set them
1087 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1088 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1089 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1090 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1091 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1092 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1093 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1094 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1095 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1096 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1097 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1098 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1099 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1100 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1101 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1102 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1103 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1104 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1105 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1106 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1107 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1108 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1109 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1110 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1111 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1112 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1113 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1114 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1115 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1116 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1117 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1118 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1119 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1120 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1121 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1122 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1123 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1124 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1125 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1126 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1127 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1128 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1129 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1130 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1131 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1132 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1133 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1134 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1135 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1136 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1137 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1138 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1139 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1140 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1141 p->loc_OffsetMapping_LodDistance = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1142 p->loc_OffsetMapping_Bias = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1143 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1144 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1145 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1146 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1147 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1148 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1149 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1150 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1151 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1152 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1153 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1154 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1155 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1156 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1157 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1158 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1159 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1160 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1161 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1162 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1163 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1164 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1165 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1166 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1167 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1168 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1169 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1170 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1171 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1172 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1173 // initialize the samplers to refer to the texture units we use
1174 p->tex_Texture_First = -1;
1175 p->tex_Texture_Second = -1;
1176 p->tex_Texture_GammaRamps = -1;
1177 p->tex_Texture_Normal = -1;
1178 p->tex_Texture_Color = -1;
1179 p->tex_Texture_Gloss = -1;
1180 p->tex_Texture_Glow = -1;
1181 p->tex_Texture_SecondaryNormal = -1;
1182 p->tex_Texture_SecondaryColor = -1;
1183 p->tex_Texture_SecondaryGloss = -1;
1184 p->tex_Texture_SecondaryGlow = -1;
1185 p->tex_Texture_Pants = -1;
1186 p->tex_Texture_Shirt = -1;
1187 p->tex_Texture_FogHeightTexture = -1;
1188 p->tex_Texture_FogMask = -1;
1189 p->tex_Texture_Lightmap = -1;
1190 p->tex_Texture_Deluxemap = -1;
1191 p->tex_Texture_Attenuation = -1;
1192 p->tex_Texture_Cube = -1;
1193 p->tex_Texture_Refraction = -1;
1194 p->tex_Texture_Reflection = -1;
1195 p->tex_Texture_ShadowMap2D = -1;
1196 p->tex_Texture_CubeProjection = -1;
1197 p->tex_Texture_ScreenNormalMap = -1;
1198 p->tex_Texture_ScreenDiffuse = -1;
1199 p->tex_Texture_ScreenSpecular = -1;
1200 p->tex_Texture_ReflectMask = -1;
1201 p->tex_Texture_ReflectCube = -1;
1202 p->tex_Texture_BounceGrid = -1;
1204 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1205 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1206 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1207 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1208 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1209 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1210 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1211 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1212 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1213 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1214 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1215 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1216 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1217 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1218 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1219 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1220 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1221 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1222 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1223 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1224 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1225 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1226 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1227 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1228 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1229 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1230 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1231 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1232 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1234 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1237 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1241 Mem_Free(vertexstring);
1243 Mem_Free(geometrystring);
1245 Mem_Free(fragmentstring);
1248 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1250 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1251 if (r_glsl_permutation != perm)
1253 r_glsl_permutation = perm;
1254 if (!r_glsl_permutation->program)
1256 if (!r_glsl_permutation->compiled)
1257 R_GLSL_CompilePermutation(perm, mode, permutation);
1258 if (!r_glsl_permutation->program)
1260 // remove features until we find a valid permutation
1262 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1264 // reduce i more quickly whenever it would not remove any bits
1265 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1266 if (!(permutation & j))
1269 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1270 if (!r_glsl_permutation->compiled)
1271 R_GLSL_CompilePermutation(perm, mode, permutation);
1272 if (r_glsl_permutation->program)
1275 if (i >= SHADERPERMUTATION_COUNT)
1277 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1278 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1279 qglUseProgram(0);CHECKGLERROR
1280 return; // no bit left to clear, entire mode is broken
1285 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1287 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1288 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1289 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1296 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1297 extern D3DCAPS9 vid_d3d9caps;
1300 struct r_hlsl_permutation_s;
1301 typedef struct r_hlsl_permutation_s
1303 /// hash lookup data
1304 struct r_hlsl_permutation_s *hashnext;
1306 unsigned int permutation;
1308 /// indicates if we have tried compiling this permutation already
1310 /// NULL if compilation failed
1311 IDirect3DVertexShader9 *vertexshader;
1312 IDirect3DPixelShader9 *pixelshader;
1314 r_hlsl_permutation_t;
1316 typedef enum D3DVSREGISTER_e
1318 D3DVSREGISTER_TexMatrix = 0, // float4x4
1319 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1320 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1321 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1322 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1323 D3DVSREGISTER_ModelToLight = 20, // float4x4
1324 D3DVSREGISTER_EyePosition = 24,
1325 D3DVSREGISTER_FogPlane = 25,
1326 D3DVSREGISTER_LightDir = 26,
1327 D3DVSREGISTER_LightPosition = 27,
1331 typedef enum D3DPSREGISTER_e
1333 D3DPSREGISTER_Alpha = 0,
1334 D3DPSREGISTER_BloomBlur_Parameters = 1,
1335 D3DPSREGISTER_ClientTime = 2,
1336 D3DPSREGISTER_Color_Ambient = 3,
1337 D3DPSREGISTER_Color_Diffuse = 4,
1338 D3DPSREGISTER_Color_Specular = 5,
1339 D3DPSREGISTER_Color_Glow = 6,
1340 D3DPSREGISTER_Color_Pants = 7,
1341 D3DPSREGISTER_Color_Shirt = 8,
1342 D3DPSREGISTER_DeferredColor_Ambient = 9,
1343 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1344 D3DPSREGISTER_DeferredColor_Specular = 11,
1345 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1346 D3DPSREGISTER_DeferredMod_Specular = 13,
1347 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1348 D3DPSREGISTER_EyePosition = 15, // unused
1349 D3DPSREGISTER_FogColor = 16,
1350 D3DPSREGISTER_FogHeightFade = 17,
1351 D3DPSREGISTER_FogPlane = 18,
1352 D3DPSREGISTER_FogPlaneViewDist = 19,
1353 D3DPSREGISTER_FogRangeRecip = 20,
1354 D3DPSREGISTER_LightColor = 21,
1355 D3DPSREGISTER_LightDir = 22, // unused
1356 D3DPSREGISTER_LightPosition = 23,
1357 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1358 D3DPSREGISTER_PixelSize = 25,
1359 D3DPSREGISTER_ReflectColor = 26,
1360 D3DPSREGISTER_ReflectFactor = 27,
1361 D3DPSREGISTER_ReflectOffset = 28,
1362 D3DPSREGISTER_RefractColor = 29,
1363 D3DPSREGISTER_Saturation = 30,
1364 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1365 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1366 D3DPSREGISTER_ScreenToDepth = 33,
1367 D3DPSREGISTER_ShadowMap_Parameters = 34,
1368 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1369 D3DPSREGISTER_SpecularPower = 36,
1370 D3DPSREGISTER_UserVec1 = 37,
1371 D3DPSREGISTER_UserVec2 = 38,
1372 D3DPSREGISTER_UserVec3 = 39,
1373 D3DPSREGISTER_UserVec4 = 40,
1374 D3DPSREGISTER_ViewTintColor = 41,
1375 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1376 D3DPSREGISTER_BloomColorSubtract = 43,
1377 D3DPSREGISTER_ViewToLight = 44, // float4x4
1378 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1379 D3DPSREGISTER_NormalmapScrollBlend = 52,
1380 D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1381 D3DPSREGISTER_OffsetMapping_Bias = 54,
1386 /// information about each possible shader permutation
1387 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1388 /// currently selected permutation
1389 r_hlsl_permutation_t *r_hlsl_permutation;
1390 /// storage for permutations linked in the hash table
1391 memexpandablearray_t r_hlsl_permutationarray;
1393 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1395 //unsigned int hashdepth = 0;
1396 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1397 r_hlsl_permutation_t *p;
1398 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1400 if (p->mode == mode && p->permutation == permutation)
1402 //if (hashdepth > 10)
1403 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1408 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1410 p->permutation = permutation;
1411 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1412 r_hlsl_permutationhash[mode][hashindex] = p;
1413 //if (hashdepth > 10)
1414 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1418 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1421 if (!filename || !filename[0])
1423 if (!strcmp(filename, "hlsl/default.hlsl"))
1425 if (!hlslshaderstring)
1427 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1428 if (hlslshaderstring)
1429 Con_DPrintf("Loading shaders from file %s...\n", filename);
1431 hlslshaderstring = (char *)builtinhlslshaderstring;
1433 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1434 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1435 return shaderstring;
1437 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1440 if (printfromdisknotice)
1441 Con_DPrintf("from disk %s... ", filename);
1442 return shaderstring;
1444 return shaderstring;
1448 //#include <d3dx9shader.h>
1449 //#include <d3dx9mesh.h>
1451 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1453 DWORD *vsbin = NULL;
1454 DWORD *psbin = NULL;
1455 fs_offset_t vsbinsize;
1456 fs_offset_t psbinsize;
1457 // IDirect3DVertexShader9 *vs = NULL;
1458 // IDirect3DPixelShader9 *ps = NULL;
1459 ID3DXBuffer *vslog = NULL;
1460 ID3DXBuffer *vsbuffer = NULL;
1461 ID3DXConstantTable *vsconstanttable = NULL;
1462 ID3DXBuffer *pslog = NULL;
1463 ID3DXBuffer *psbuffer = NULL;
1464 ID3DXConstantTable *psconstanttable = NULL;
1467 char temp[MAX_INPUTLINE];
1468 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(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1476 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%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(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1528 FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1529 vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%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_DPrintf("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(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1553 FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1554 psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%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_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1572 Sys_UnloadLibrary(&d3dx9_dll);
1575 Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1579 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1580 if (FAILED(vsresult))
1581 Con_DPrintf("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_DPrintf("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+5+SHADERSTATICPARMS_COUNT+1];
1607 const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1608 const char *fragstrings_list[32+5+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 static 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 static 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, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1909 unsigned int permutation = 0;
1910 if (r_trippy.integer && !notrippy)
1911 permutation |= SHADERPERMUTATION_TRIPPY;
1912 permutation |= SHADERPERMUTATION_VIEWTINT;
1914 permutation |= SHADERPERMUTATION_DIFFUSE;
1916 permutation |= SHADERPERMUTATION_SPECULAR;
1917 if (texturemode == GL_MODULATE)
1918 permutation |= SHADERPERMUTATION_COLORMAPPING;
1919 else if (texturemode == GL_ADD)
1920 permutation |= SHADERPERMUTATION_GLOW;
1921 else if (texturemode == GL_DECAL)
1922 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1923 if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1924 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1925 if (suppresstexalpha)
1926 permutation |= SHADERPERMUTATION_REFLECTCUBE;
1928 texturemode = GL_MODULATE;
1929 if (vid.allowalphatocoverage)
1930 GL_AlphaToCoverage(false);
1931 switch (vid.renderpath)
1933 case RENDERPATH_D3D9:
1935 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1936 R_Mesh_TexBind(GL20TU_FIRST , first );
1937 R_Mesh_TexBind(GL20TU_SECOND, second);
1938 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1939 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1942 case RENDERPATH_D3D10:
1943 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1945 case RENDERPATH_D3D11:
1946 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1948 case RENDERPATH_GL20:
1949 case RENDERPATH_GLES2:
1950 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1951 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1952 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1953 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1954 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1956 case RENDERPATH_GL13:
1957 case RENDERPATH_GLES1:
1958 R_Mesh_TexBind(0, first );
1959 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1960 R_Mesh_TexBind(1, second);
1962 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1964 case RENDERPATH_GL11:
1965 R_Mesh_TexBind(0, first );
1967 case RENDERPATH_SOFT:
1968 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1969 R_Mesh_TexBind(GL20TU_FIRST , first );
1970 R_Mesh_TexBind(GL20TU_SECOND, second);
1975 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
1977 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
1980 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb)
1982 unsigned int permutation = 0;
1983 if (r_trippy.integer && !notrippy)
1984 permutation |= SHADERPERMUTATION_TRIPPY;
1986 permutation |= SHADERPERMUTATION_DEPTHRGB;
1987 if (vid.allowalphatocoverage)
1988 GL_AlphaToCoverage(false);
1989 switch (vid.renderpath)
1991 case RENDERPATH_D3D9:
1993 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1996 case RENDERPATH_D3D10:
1997 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1999 case RENDERPATH_D3D11:
2000 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2002 case RENDERPATH_GL20:
2003 case RENDERPATH_GLES2:
2004 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2006 case RENDERPATH_GL13:
2007 case RENDERPATH_GLES1:
2008 R_Mesh_TexBind(0, 0);
2009 R_Mesh_TexBind(1, 0);
2011 case RENDERPATH_GL11:
2012 R_Mesh_TexBind(0, 0);
2014 case RENDERPATH_SOFT:
2015 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2020 void R_SetupShader_ShowDepth(qboolean notrippy)
2022 int permutation = 0;
2023 if (r_trippy.integer && !notrippy)
2024 permutation |= SHADERPERMUTATION_TRIPPY;
2025 if (vid.allowalphatocoverage)
2026 GL_AlphaToCoverage(false);
2027 switch (vid.renderpath)
2029 case RENDERPATH_D3D9:
2031 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2034 case RENDERPATH_D3D10:
2035 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2037 case RENDERPATH_D3D11:
2038 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2040 case RENDERPATH_GL20:
2041 case RENDERPATH_GLES2:
2042 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2044 case RENDERPATH_GL13:
2045 case RENDERPATH_GLES1:
2047 case RENDERPATH_GL11:
2049 case RENDERPATH_SOFT:
2050 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2055 extern qboolean r_shadow_usingdeferredprepass;
2056 extern rtexture_t *r_shadow_attenuationgradienttexture;
2057 extern rtexture_t *r_shadow_attenuation2dtexture;
2058 extern rtexture_t *r_shadow_attenuation3dtexture;
2059 extern qboolean r_shadow_usingshadowmap2d;
2060 extern qboolean r_shadow_usingshadowmaportho;
2061 extern float r_shadow_shadowmap_texturescale[2];
2062 extern float r_shadow_shadowmap_parameters[4];
2063 extern qboolean r_shadow_shadowmapvsdct;
2064 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2065 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2066 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2067 extern matrix4x4_t r_shadow_shadowmapmatrix;
2068 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2069 extern int r_shadow_prepass_width;
2070 extern int r_shadow_prepass_height;
2071 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2072 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2073 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2074 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2076 #define BLENDFUNC_ALLOWS_COLORMOD 1
2077 #define BLENDFUNC_ALLOWS_FOG 2
2078 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2079 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2080 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2081 static int R_BlendFuncFlags(int src, int dst)
2085 // a blendfunc allows colormod if:
2086 // a) it can never keep the destination pixel invariant, or
2087 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2088 // this is to prevent unintended side effects from colormod
2090 // a blendfunc allows fog if:
2091 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2092 // this is to prevent unintended side effects from fog
2094 // these checks are the output of fogeval.pl
2096 r |= BLENDFUNC_ALLOWS_COLORMOD;
2097 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2098 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2099 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2100 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2101 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2102 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2103 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2104 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2105 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2106 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2107 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2108 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2109 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2110 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2111 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2112 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2113 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2114 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2115 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2116 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2117 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2122 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, qboolean notrippy)
2124 // select a permutation of the lighting shader appropriate to this
2125 // combination of texture, entity, light source, and fogging, only use the
2126 // minimum features necessary to avoid wasting rendering time in the
2127 // fragment shader on features that are not being used
2128 unsigned int permutation = 0;
2129 unsigned int mode = 0;
2131 static float dummy_colormod[3] = {1, 1, 1};
2132 float *colormod = rsurface.colormod;
2134 matrix4x4_t tempmatrix;
2135 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2136 if (r_trippy.integer && !notrippy)
2137 permutation |= SHADERPERMUTATION_TRIPPY;
2138 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2139 permutation |= SHADERPERMUTATION_ALPHAKILL;
2140 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2141 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2142 if (rsurfacepass == RSURFPASS_BACKGROUND)
2144 // distorted background
2145 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2147 mode = SHADERMODE_WATER;
2148 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2150 // this is the right thing to do for wateralpha
2151 GL_BlendFunc(GL_ONE, GL_ZERO);
2152 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2156 // this is the right thing to do for entity alpha
2157 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2158 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2161 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2163 mode = SHADERMODE_REFRACTION;
2164 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2165 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2169 mode = SHADERMODE_GENERIC;
2170 permutation |= SHADERPERMUTATION_DIFFUSE;
2171 GL_BlendFunc(GL_ONE, GL_ZERO);
2172 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2174 if (vid.allowalphatocoverage)
2175 GL_AlphaToCoverage(false);
2177 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2179 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2181 switch(rsurface.texture->offsetmapping)
2183 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2184 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2185 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2186 case OFFSETMAPPING_OFF: break;
2189 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2190 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2191 // normalmap (deferred prepass), may use alpha test on diffuse
2192 mode = SHADERMODE_DEFERREDGEOMETRY;
2193 GL_BlendFunc(GL_ONE, GL_ZERO);
2194 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2195 if (vid.allowalphatocoverage)
2196 GL_AlphaToCoverage(false);
2198 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2200 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2202 switch(rsurface.texture->offsetmapping)
2204 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2205 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2206 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2207 case OFFSETMAPPING_OFF: break;
2210 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2211 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2213 mode = SHADERMODE_LIGHTSOURCE;
2214 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2215 permutation |= SHADERPERMUTATION_CUBEFILTER;
2216 if (diffusescale > 0)
2217 permutation |= SHADERPERMUTATION_DIFFUSE;
2218 if (specularscale > 0)
2219 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2220 if (r_refdef.fogenabled)
2221 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2222 if (rsurface.texture->colormapping)
2223 permutation |= SHADERPERMUTATION_COLORMAPPING;
2224 if (r_shadow_usingshadowmap2d)
2226 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2227 if(r_shadow_shadowmapvsdct)
2228 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2230 if (r_shadow_shadowmap2ddepthbuffer)
2231 permutation |= SHADERPERMUTATION_DEPTHRGB;
2233 if (rsurface.texture->reflectmasktexture)
2234 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2235 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2236 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2237 if (vid.allowalphatocoverage)
2238 GL_AlphaToCoverage(false);
2240 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2242 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2244 switch(rsurface.texture->offsetmapping)
2246 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2247 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2248 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2249 case OFFSETMAPPING_OFF: break;
2252 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2253 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2254 // unshaded geometry (fullbright or ambient model lighting)
2255 mode = SHADERMODE_FLATCOLOR;
2256 ambientscale = diffusescale = specularscale = 0;
2257 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2258 permutation |= SHADERPERMUTATION_GLOW;
2259 if (r_refdef.fogenabled)
2260 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2261 if (rsurface.texture->colormapping)
2262 permutation |= SHADERPERMUTATION_COLORMAPPING;
2263 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2265 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2266 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2268 if (r_shadow_shadowmap2ddepthbuffer)
2269 permutation |= SHADERPERMUTATION_DEPTHRGB;
2271 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2272 permutation |= SHADERPERMUTATION_REFLECTION;
2273 if (rsurface.texture->reflectmasktexture)
2274 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2275 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2276 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2277 // when using alphatocoverage, we don't need alphakill
2278 if (vid.allowalphatocoverage)
2280 if (r_transparent_alphatocoverage.integer)
2282 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2283 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2286 GL_AlphaToCoverage(false);
2289 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2291 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2293 switch(rsurface.texture->offsetmapping)
2295 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2296 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2297 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2298 case OFFSETMAPPING_OFF: break;
2301 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2302 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2303 // directional model lighting
2304 mode = SHADERMODE_LIGHTDIRECTION;
2305 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2306 permutation |= SHADERPERMUTATION_GLOW;
2307 permutation |= SHADERPERMUTATION_DIFFUSE;
2308 if (specularscale > 0)
2309 permutation |= SHADERPERMUTATION_SPECULAR;
2310 if (r_refdef.fogenabled)
2311 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2312 if (rsurface.texture->colormapping)
2313 permutation |= SHADERPERMUTATION_COLORMAPPING;
2314 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2316 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2317 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2319 if (r_shadow_shadowmap2ddepthbuffer)
2320 permutation |= SHADERPERMUTATION_DEPTHRGB;
2322 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2323 permutation |= SHADERPERMUTATION_REFLECTION;
2324 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2325 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2326 if (rsurface.texture->reflectmasktexture)
2327 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2328 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2330 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2331 if (r_shadow_bouncegriddirectional)
2332 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2334 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2335 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2336 // when using alphatocoverage, we don't need alphakill
2337 if (vid.allowalphatocoverage)
2339 if (r_transparent_alphatocoverage.integer)
2341 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2342 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2345 GL_AlphaToCoverage(false);
2348 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2350 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2352 switch(rsurface.texture->offsetmapping)
2354 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2355 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2356 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2357 case OFFSETMAPPING_OFF: break;
2360 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2361 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2362 // ambient model lighting
2363 mode = SHADERMODE_LIGHTDIRECTION;
2364 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2365 permutation |= SHADERPERMUTATION_GLOW;
2366 if (r_refdef.fogenabled)
2367 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2368 if (rsurface.texture->colormapping)
2369 permutation |= SHADERPERMUTATION_COLORMAPPING;
2370 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2372 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2373 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2375 if (r_shadow_shadowmap2ddepthbuffer)
2376 permutation |= SHADERPERMUTATION_DEPTHRGB;
2378 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2379 permutation |= SHADERPERMUTATION_REFLECTION;
2380 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2381 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2382 if (rsurface.texture->reflectmasktexture)
2383 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2384 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2386 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2387 if (r_shadow_bouncegriddirectional)
2388 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2390 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2391 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2392 // when using alphatocoverage, we don't need alphakill
2393 if (vid.allowalphatocoverage)
2395 if (r_transparent_alphatocoverage.integer)
2397 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2398 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2401 GL_AlphaToCoverage(false);
2406 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2408 switch(rsurface.texture->offsetmapping)
2410 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2411 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2412 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2413 case OFFSETMAPPING_OFF: break;
2416 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2417 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2419 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2420 permutation |= SHADERPERMUTATION_GLOW;
2421 if (r_refdef.fogenabled)
2422 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2423 if (rsurface.texture->colormapping)
2424 permutation |= SHADERPERMUTATION_COLORMAPPING;
2425 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2427 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2428 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2430 if (r_shadow_shadowmap2ddepthbuffer)
2431 permutation |= SHADERPERMUTATION_DEPTHRGB;
2433 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2434 permutation |= SHADERPERMUTATION_REFLECTION;
2435 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2436 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2437 if (rsurface.texture->reflectmasktexture)
2438 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2439 if (FAKELIGHT_ENABLED)
2441 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2442 mode = SHADERMODE_FAKELIGHT;
2443 permutation |= SHADERPERMUTATION_DIFFUSE;
2444 if (specularscale > 0)
2445 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2447 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2449 // deluxemapping (light direction texture)
2450 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2451 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2453 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2454 permutation |= SHADERPERMUTATION_DIFFUSE;
2455 if (specularscale > 0)
2456 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2458 else if (r_glsl_deluxemapping.integer >= 2)
2460 // fake deluxemapping (uniform light direction in tangentspace)
2461 if (rsurface.uselightmaptexture)
2462 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2464 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2465 permutation |= SHADERPERMUTATION_DIFFUSE;
2466 if (specularscale > 0)
2467 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2469 else if (rsurface.uselightmaptexture)
2471 // ordinary lightmapping (q1bsp, q3bsp)
2472 mode = SHADERMODE_LIGHTMAP;
2476 // ordinary vertex coloring (q3bsp)
2477 mode = SHADERMODE_VERTEXCOLOR;
2479 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2481 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2482 if (r_shadow_bouncegriddirectional)
2483 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2485 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2486 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2487 // when using alphatocoverage, we don't need alphakill
2488 if (vid.allowalphatocoverage)
2490 if (r_transparent_alphatocoverage.integer)
2492 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2493 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2496 GL_AlphaToCoverage(false);
2499 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2500 colormod = dummy_colormod;
2501 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2502 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2503 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2504 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2505 switch(vid.renderpath)
2507 case RENDERPATH_D3D9:
2509 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);
2510 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2511 R_SetupShader_SetPermutationHLSL(mode, permutation);
2512 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2513 if (mode == SHADERMODE_LIGHTSOURCE)
2515 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2516 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2520 if (mode == SHADERMODE_LIGHTDIRECTION)
2522 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2525 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2526 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2527 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2528 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2529 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2531 if (mode == SHADERMODE_LIGHTSOURCE)
2533 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2534 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2535 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2536 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2537 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2539 // additive passes are only darkened by fog, not tinted
2540 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2541 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2545 if (mode == SHADERMODE_FLATCOLOR)
2547 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2549 else if (mode == SHADERMODE_LIGHTDIRECTION)
2551 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]);
2552 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2553 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);
2554 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2555 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2556 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2557 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2561 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2562 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2563 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);
2564 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2565 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2567 // additive passes are only darkened by fog, not tinted
2568 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2569 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2571 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2572 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);
2573 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2574 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2575 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2576 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2577 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2578 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2579 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2580 if (mode == SHADERMODE_WATER)
2581 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2583 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2584 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2585 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2586 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2587 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2588 if (rsurface.texture->pantstexture)
2589 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2591 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2592 if (rsurface.texture->shirttexture)
2593 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2595 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2596 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2597 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2598 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2599 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2600 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2601 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2602 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2603 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2604 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2606 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2607 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2608 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2609 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2611 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2612 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2613 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2614 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2615 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2616 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2617 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2618 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2619 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2620 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2621 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2622 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2623 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2624 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2625 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2626 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2627 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2628 if (rsurfacepass == RSURFPASS_BACKGROUND)
2630 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2631 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2632 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2636 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2638 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2639 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2640 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2641 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2643 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2644 if (rsurface.rtlight)
2646 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2647 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2652 case RENDERPATH_D3D10:
2653 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2655 case RENDERPATH_D3D11:
2656 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2658 case RENDERPATH_GL20:
2659 case RENDERPATH_GLES2:
2660 if (!vid.useinterleavedarrays)
2662 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);
2663 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2664 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2665 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2666 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2667 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2668 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2669 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2673 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);
2674 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2676 R_SetupShader_SetPermutationGLSL(mode, permutation);
2677 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2678 if (mode == SHADERMODE_LIGHTSOURCE)
2680 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2681 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2682 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2683 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2684 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2685 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);
2687 // additive passes are only darkened by fog, not tinted
2688 if (r_glsl_permutation->loc_FogColor >= 0)
2689 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2690 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2694 if (mode == SHADERMODE_FLATCOLOR)
2696 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2698 else if (mode == SHADERMODE_LIGHTDIRECTION)
2700 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]);
2701 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]);
2702 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);
2703 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2704 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2705 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]);
2706 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]);
2710 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]);
2711 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]);
2712 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);
2713 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2714 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2716 // additive passes are only darkened by fog, not tinted
2717 if (r_glsl_permutation->loc_FogColor >= 0)
2719 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2720 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2722 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2724 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);
2725 if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2726 if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2727 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]);
2728 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]);
2729 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2730 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2731 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2732 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]);
2734 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2735 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2736 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2737 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]);
2738 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]);
2740 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2741 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2742 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2743 if (r_glsl_permutation->loc_Color_Pants >= 0)
2745 if (rsurface.texture->pantstexture)
2746 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2748 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2750 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2752 if (rsurface.texture->shirttexture)
2753 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2755 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2757 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]);
2758 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2759 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2760 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2761 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2762 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2763 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2764 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2765 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2767 if (r_glsl_permutation->loc_OffsetMapping_LodDistance >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2768 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2769 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]);
2770 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2771 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);}
2772 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2774 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2775 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2776 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2777 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2778 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2779 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2780 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2781 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2782 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2783 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2784 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2785 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2786 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2787 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2788 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);
2789 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2790 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2791 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2792 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2793 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2794 if (rsurfacepass == RSURFPASS_BACKGROUND)
2796 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);
2797 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);
2798 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);
2802 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);
2804 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2805 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2806 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2807 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2809 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture );
2810 if (rsurface.rtlight)
2812 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2813 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2816 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2819 case RENDERPATH_GL11:
2820 case RENDERPATH_GL13:
2821 case RENDERPATH_GLES1:
2823 case RENDERPATH_SOFT:
2824 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);
2825 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2826 R_SetupShader_SetPermutationSoft(mode, permutation);
2827 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2828 if (mode == SHADERMODE_LIGHTSOURCE)
2830 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2831 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2832 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2833 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2834 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2835 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2837 // additive passes are only darkened by fog, not tinted
2838 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2839 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2843 if (mode == SHADERMODE_FLATCOLOR)
2845 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2847 else if (mode == SHADERMODE_LIGHTDIRECTION)
2849 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]);
2850 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2851 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);
2852 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2853 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2854 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]);
2855 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2859 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2860 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2861 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);
2862 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2863 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2865 // additive passes are only darkened by fog, not tinted
2866 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2867 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2869 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2870 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);
2871 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2872 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2873 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]);
2874 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]);
2875 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2876 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2877 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2878 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2880 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2881 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2882 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2883 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2884 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]);
2886 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2887 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2888 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2889 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2891 if (rsurface.texture->pantstexture)
2892 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2894 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2896 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2898 if (rsurface.texture->shirttexture)
2899 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2901 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2903 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2904 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2905 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2906 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2907 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2908 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2909 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2910 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2911 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2913 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2914 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2915 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2916 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2918 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2919 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2920 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2921 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2922 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2923 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2924 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2925 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2926 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2927 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2928 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2929 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2930 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2931 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2932 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2933 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2934 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2935 if (rsurfacepass == RSURFPASS_BACKGROUND)
2937 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2938 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2939 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2943 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2945 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2946 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2947 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2948 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2950 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2951 if (rsurface.rtlight)
2953 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2954 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2961 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2963 // select a permutation of the lighting shader appropriate to this
2964 // combination of texture, entity, light source, and fogging, only use the
2965 // minimum features necessary to avoid wasting rendering time in the
2966 // fragment shader on features that are not being used
2967 unsigned int permutation = 0;
2968 unsigned int mode = 0;
2969 const float *lightcolorbase = rtlight->currentcolor;
2970 float ambientscale = rtlight->ambientscale;
2971 float diffusescale = rtlight->diffusescale;
2972 float specularscale = rtlight->specularscale;
2973 // this is the location of the light in view space
2974 vec3_t viewlightorigin;
2975 // this transforms from view space (camera) to light space (cubemap)
2976 matrix4x4_t viewtolight;
2977 matrix4x4_t lighttoview;
2978 float viewtolight16f[16];
2980 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2981 if (rtlight->currentcubemap != r_texture_whitecube)
2982 permutation |= SHADERPERMUTATION_CUBEFILTER;
2983 if (diffusescale > 0)
2984 permutation |= SHADERPERMUTATION_DIFFUSE;
2985 if (specularscale > 0 && r_shadow_gloss.integer > 0)
2986 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2987 if (r_shadow_usingshadowmap2d)
2989 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2990 if (r_shadow_shadowmapvsdct)
2991 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2993 if (r_shadow_shadowmap2ddepthbuffer)
2994 permutation |= SHADERPERMUTATION_DEPTHRGB;
2996 if (vid.allowalphatocoverage)
2997 GL_AlphaToCoverage(false);
2998 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2999 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3000 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3001 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3002 switch(vid.renderpath)
3004 case RENDERPATH_D3D9:
3006 R_SetupShader_SetPermutationHLSL(mode, permutation);
3007 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3008 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3009 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3010 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3011 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3012 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3013 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3014 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3015 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3016 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3018 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3019 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3020 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3021 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2ddepthtexture );
3022 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3025 case RENDERPATH_D3D10:
3026 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3028 case RENDERPATH_D3D11:
3029 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3031 case RENDERPATH_GL20:
3032 case RENDERPATH_GLES2:
3033 R_SetupShader_SetPermutationGLSL(mode, permutation);
3034 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3035 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
3036 if (r_glsl_permutation->loc_DeferredColor_Ambient >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3037 if (r_glsl_permutation->loc_DeferredColor_Diffuse >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3038 if (r_glsl_permutation->loc_DeferredColor_Specular >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3039 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]);
3040 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]);
3041 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) - 1.0f);
3042 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]);
3043 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
3045 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
3046 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
3047 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
3048 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2ddepthtexture );
3049 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
3051 case RENDERPATH_GL11:
3052 case RENDERPATH_GL13:
3053 case RENDERPATH_GLES1:
3055 case RENDERPATH_SOFT:
3056 R_SetupShader_SetPermutationGLSL(mode, permutation);
3057 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3058 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
3059 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3060 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3061 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3062 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3063 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]);
3064 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) - 1.0f);
3065 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3066 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3068 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3069 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3070 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3071 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2ddepthtexture );
3072 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3077 #define SKINFRAME_HASH 1024
3081 int loadsequence; // incremented each level change
3082 memexpandablearray_t array;
3083 skinframe_t *hash[SKINFRAME_HASH];
3086 r_skinframe_t r_skinframe;
3088 void R_SkinFrame_PrepareForPurge(void)
3090 r_skinframe.loadsequence++;
3091 // wrap it without hitting zero
3092 if (r_skinframe.loadsequence >= 200)
3093 r_skinframe.loadsequence = 1;
3096 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3100 // mark the skinframe as used for the purging code
3101 skinframe->loadsequence = r_skinframe.loadsequence;
3104 void R_SkinFrame_Purge(void)
3108 for (i = 0;i < SKINFRAME_HASH;i++)
3110 for (s = r_skinframe.hash[i];s;s = s->next)
3112 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3114 if (s->merged == s->base)
3116 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3117 R_PurgeTexture(s->stain );s->stain = NULL;
3118 R_PurgeTexture(s->merged);s->merged = NULL;
3119 R_PurgeTexture(s->base );s->base = NULL;
3120 R_PurgeTexture(s->pants );s->pants = NULL;
3121 R_PurgeTexture(s->shirt );s->shirt = NULL;
3122 R_PurgeTexture(s->nmap );s->nmap = NULL;
3123 R_PurgeTexture(s->gloss );s->gloss = NULL;
3124 R_PurgeTexture(s->glow );s->glow = NULL;
3125 R_PurgeTexture(s->fog );s->fog = NULL;
3126 R_PurgeTexture(s->reflect);s->reflect = NULL;
3127 s->loadsequence = 0;
3133 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3135 char basename[MAX_QPATH];
3137 Image_StripImageExtension(name, basename, sizeof(basename));
3139 if( last == NULL ) {
3141 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3142 item = r_skinframe.hash[hashindex];
3147 // linearly search through the hash bucket
3148 for( ; item ; item = item->next ) {
3149 if( !strcmp( item->basename, basename ) ) {
3156 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3160 char basename[MAX_QPATH];
3162 Image_StripImageExtension(name, basename, sizeof(basename));
3164 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3165 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3166 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3170 rtexture_t *dyntexture;
3171 // check whether its a dynamic texture
3172 dyntexture = CL_GetDynTexture( basename );
3173 if (!add && !dyntexture)
3175 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3176 memset(item, 0, sizeof(*item));
3177 strlcpy(item->basename, basename, sizeof(item->basename));
3178 item->base = dyntexture; // either NULL or dyntexture handle
3179 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3180 item->comparewidth = comparewidth;
3181 item->compareheight = compareheight;
3182 item->comparecrc = comparecrc;
3183 item->next = r_skinframe.hash[hashindex];
3184 r_skinframe.hash[hashindex] = item;
3186 else if (textureflags & TEXF_FORCE_RELOAD)
3188 rtexture_t *dyntexture;
3189 // check whether its a dynamic texture
3190 dyntexture = CL_GetDynTexture( basename );
3191 if (!add && !dyntexture)
3193 if (item->merged == item->base)
3194 item->merged = NULL;
3195 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3196 R_PurgeTexture(item->stain );item->stain = NULL;
3197 R_PurgeTexture(item->merged);item->merged = NULL;
3198 R_PurgeTexture(item->base );item->base = NULL;
3199 R_PurgeTexture(item->pants );item->pants = NULL;
3200 R_PurgeTexture(item->shirt );item->shirt = NULL;
3201 R_PurgeTexture(item->nmap );item->nmap = NULL;
3202 R_PurgeTexture(item->gloss );item->gloss = NULL;
3203 R_PurgeTexture(item->glow );item->glow = NULL;
3204 R_PurgeTexture(item->fog );item->fog = NULL;
3205 R_PurgeTexture(item->reflect);item->reflect = NULL;
3206 item->loadsequence = 0;
3208 else if( item->base == NULL )
3210 rtexture_t *dyntexture;
3211 // check whether its a dynamic texture
3212 // 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]
3213 dyntexture = CL_GetDynTexture( basename );
3214 item->base = dyntexture; // either NULL or dyntexture handle
3217 R_SkinFrame_MarkUsed(item);
3221 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3223 unsigned long long avgcolor[5], wsum; \
3231 for(pix = 0; pix < cnt; ++pix) \
3234 for(comp = 0; comp < 3; ++comp) \
3236 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3239 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3241 for(comp = 0; comp < 3; ++comp) \
3242 avgcolor[comp] += getpixel * w; \
3245 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3246 avgcolor[4] += getpixel; \
3248 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3250 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3251 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3252 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3253 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3256 extern cvar_t gl_picmip;
3257 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3260 unsigned char *pixels;
3261 unsigned char *bumppixels;
3262 unsigned char *basepixels = NULL;
3263 int basepixels_width = 0;
3264 int basepixels_height = 0;
3265 skinframe_t *skinframe;
3266 rtexture_t *ddsbase = NULL;
3267 qboolean ddshasalpha = false;
3268 float ddsavgcolor[4];
3269 char basename[MAX_QPATH];
3270 int miplevel = R_PicmipForFlags(textureflags);
3271 int savemiplevel = miplevel;
3275 if (cls.state == ca_dedicated)
3278 // return an existing skinframe if already loaded
3279 // if loading of the first image fails, don't make a new skinframe as it
3280 // would cause all future lookups of this to be missing
3281 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3282 if (skinframe && skinframe->base)
3285 Image_StripImageExtension(name, basename, sizeof(basename));
3287 // check for DDS texture file first
3288 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3290 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3291 if (basepixels == NULL)
3295 // FIXME handle miplevel
3297 if (developer_loading.integer)
3298 Con_Printf("loading skin \"%s\"\n", name);
3300 // we've got some pixels to store, so really allocate this new texture now
3302 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3303 textureflags &= ~TEXF_FORCE_RELOAD;
3304 skinframe->stain = NULL;
3305 skinframe->merged = NULL;
3306 skinframe->base = NULL;
3307 skinframe->pants = NULL;
3308 skinframe->shirt = NULL;
3309 skinframe->nmap = NULL;
3310 skinframe->gloss = NULL;
3311 skinframe->glow = NULL;
3312 skinframe->fog = NULL;
3313 skinframe->reflect = NULL;
3314 skinframe->hasalpha = false;
3318 skinframe->base = ddsbase;
3319 skinframe->hasalpha = ddshasalpha;
3320 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3321 if (r_loadfog && skinframe->hasalpha)
3322 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), false, textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3323 //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]);
3327 basepixels_width = image_width;
3328 basepixels_height = image_height;
3329 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3330 if (textureflags & TEXF_ALPHA)
3332 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3334 if (basepixels[j] < 255)
3336 skinframe->hasalpha = true;
3340 if (r_loadfog && skinframe->hasalpha)
3342 // has transparent pixels
3343 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3344 for (j = 0;j < image_width * image_height * 4;j += 4)
3349 pixels[j+3] = basepixels[j+3];
3351 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3355 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3357 //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]);
3358 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3359 R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3360 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3361 R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3367 mymiplevel = savemiplevel;
3368 if (r_loadnormalmap)
3369 skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), false, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel);
3370 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3372 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3373 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3374 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3375 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3378 // _norm is the name used by tenebrae and has been adopted as standard
3379 if (r_loadnormalmap && skinframe->nmap == NULL)
3381 mymiplevel = savemiplevel;
3382 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3384 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3388 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3390 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3391 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3392 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3394 Mem_Free(bumppixels);
3396 else if (r_shadow_bumpscale_basetexture.value > 0)
3398 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3399 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3400 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3404 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3405 R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3409 // _luma is supported only for tenebrae compatibility
3410 // _glow is the preferred name
3411 mymiplevel = savemiplevel;
3412 if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_glow", skinframe->basename), false, false, false, &mymiplevel)) || (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_luma", skinframe->basename), false, false, false, &mymiplevel))))
3414 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_glow", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3416 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3417 R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3419 Mem_Free(pixels);pixels = NULL;
3422 mymiplevel = savemiplevel;
3423 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3425 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (gl_texturecompression_gloss.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3427 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3428 R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3434 mymiplevel = savemiplevel;
3435 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3437 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3439 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3440 R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3446 mymiplevel = savemiplevel;
3447 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3449 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3451 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3452 R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3458 mymiplevel = savemiplevel;
3459 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3461 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3463 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3464 R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3471 Mem_Free(basepixels);
3476 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3477 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3480 unsigned char *temp1, *temp2;
3481 skinframe_t *skinframe;
3484 if (cls.state == ca_dedicated)
3487 // if already loaded just return it, otherwise make a new skinframe
3488 skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3489 if (skinframe && skinframe->base)
3491 textureflags &= ~TEXF_FORCE_RELOAD;
3493 skinframe->stain = NULL;
3494 skinframe->merged = NULL;
3495 skinframe->base = NULL;
3496 skinframe->pants = NULL;
3497 skinframe->shirt = NULL;
3498 skinframe->nmap = NULL;
3499 skinframe->gloss = NULL;
3500 skinframe->glow = NULL;
3501 skinframe->fog = NULL;
3502 skinframe->reflect = NULL;
3503 skinframe->hasalpha = false;
3505 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3509 if (developer_loading.integer)
3510 Con_Printf("loading 32bit skin \"%s\"\n", name);
3512 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3514 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3515 temp2 = temp1 + width * height * 4;
3516 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3517 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3520 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3521 if (textureflags & TEXF_ALPHA)
3523 for (i = 3;i < width * height * 4;i += 4)
3525 if (skindata[i] < 255)
3527 skinframe->hasalpha = true;
3531 if (r_loadfog && skinframe->hasalpha)
3533 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3534 memcpy(fogpixels, skindata, width * height * 4);
3535 for (i = 0;i < width * height * 4;i += 4)
3536 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3537 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3538 Mem_Free(fogpixels);
3542 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3543 //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]);
3548 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3552 skinframe_t *skinframe;
3554 if (cls.state == ca_dedicated)
3557 // if already loaded just return it, otherwise make a new skinframe
3558 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3559 if (skinframe && skinframe->base)
3561 textureflags &= ~TEXF_FORCE_RELOAD;
3563 skinframe->stain = NULL;
3564 skinframe->merged = NULL;
3565 skinframe->base = NULL;
3566 skinframe->pants = NULL;
3567 skinframe->shirt = NULL;
3568 skinframe->nmap = NULL;
3569 skinframe->gloss = NULL;
3570 skinframe->glow = NULL;
3571 skinframe->fog = NULL;
3572 skinframe->reflect = NULL;
3573 skinframe->hasalpha = false;
3575 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3579 if (developer_loading.integer)
3580 Con_Printf("loading quake skin \"%s\"\n", name);
3582 // 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)
3583 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3584 memcpy(skinframe->qpixels, skindata, width*height);
3585 skinframe->qwidth = width;
3586 skinframe->qheight = height;
3589 for (i = 0;i < width * height;i++)
3590 featuresmask |= palette_featureflags[skindata[i]];
3592 skinframe->hasalpha = false;
3593 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3594 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3595 skinframe->qgeneratemerged = true;
3596 skinframe->qgeneratebase = skinframe->qhascolormapping;
3597 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3599 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3600 //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]);
3605 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3609 unsigned char *skindata;
3612 if (!skinframe->qpixels)
3615 if (!skinframe->qhascolormapping)
3616 colormapped = false;
3620 if (!skinframe->qgeneratebase)
3625 if (!skinframe->qgeneratemerged)
3629 width = skinframe->qwidth;
3630 height = skinframe->qheight;
3631 skindata = skinframe->qpixels;
3633 if (skinframe->qgeneratenmap)
3635 unsigned char *temp1, *temp2;
3636 skinframe->qgeneratenmap = false;
3637 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3638 temp2 = temp1 + width * height * 4;
3639 // use either a custom palette or the quake palette
3640 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3641 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3642 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3646 if (skinframe->qgenerateglow)
3648 skinframe->qgenerateglow = false;
3649 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_glow", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3654 skinframe->qgeneratebase = false;
3655 skinframe->base = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nospecial", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
3656 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3657 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3661 skinframe->qgeneratemerged = false;
3662 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
3665 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3667 Mem_Free(skinframe->qpixels);
3668 skinframe->qpixels = NULL;
3672 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)
3675 skinframe_t *skinframe;
3678 if (cls.state == ca_dedicated)
3681 // if already loaded just return it, otherwise make a new skinframe
3682 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3683 if (skinframe && skinframe->base)
3685 textureflags &= ~TEXF_FORCE_RELOAD;
3687 skinframe->stain = NULL;
3688 skinframe->merged = NULL;
3689 skinframe->base = NULL;
3690 skinframe->pants = NULL;
3691 skinframe->shirt = NULL;
3692 skinframe->nmap = NULL;
3693 skinframe->gloss = NULL;
3694 skinframe->glow = NULL;
3695 skinframe->fog = NULL;
3696 skinframe->reflect = NULL;
3697 skinframe->hasalpha = false;
3699 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3703 if (developer_loading.integer)
3704 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3706 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3707 if (textureflags & TEXF_ALPHA)
3709 for (i = 0;i < width * height;i++)
3711 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3713 skinframe->hasalpha = true;
3717 if (r_loadfog && skinframe->hasalpha)
3718 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3721 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3722 //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]);
3727 skinframe_t *R_SkinFrame_LoadMissing(void)
3729 skinframe_t *skinframe;
3731 if (cls.state == ca_dedicated)
3734 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3735 skinframe->stain = NULL;
3736 skinframe->merged = NULL;
3737 skinframe->base = NULL;
3738 skinframe->pants = NULL;
3739 skinframe->shirt = NULL;
3740 skinframe->nmap = NULL;
3741 skinframe->gloss = NULL;
3742 skinframe->glow = NULL;
3743 skinframe->fog = NULL;
3744 skinframe->reflect = NULL;
3745 skinframe->hasalpha = false;
3747 skinframe->avgcolor[0] = rand() / RAND_MAX;
3748 skinframe->avgcolor[1] = rand() / RAND_MAX;
3749 skinframe->avgcolor[2] = rand() / RAND_MAX;
3750 skinframe->avgcolor[3] = 1;
3755 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3756 typedef struct suffixinfo_s
3759 qboolean flipx, flipy, flipdiagonal;
3762 static suffixinfo_t suffix[3][6] =
3765 {"px", false, false, false},
3766 {"nx", false, false, false},
3767 {"py", false, false, false},
3768 {"ny", false, false, false},
3769 {"pz", false, false, false},
3770 {"nz", false, false, false}
3773 {"posx", false, false, false},
3774 {"negx", false, false, false},
3775 {"posy", false, false, false},
3776 {"negy", false, false, false},
3777 {"posz", false, false, false},
3778 {"negz", false, false, false}
3781 {"rt", true, false, true},
3782 {"lf", false, true, true},
3783 {"ft", true, true, false},
3784 {"bk", false, false, false},
3785 {"up", true, false, true},
3786 {"dn", true, false, true}
3790 static int componentorder[4] = {0, 1, 2, 3};
3792 static rtexture_t *R_LoadCubemap(const char *basename)
3794 int i, j, cubemapsize;
3795 unsigned char *cubemappixels, *image_buffer;
3796 rtexture_t *cubemaptexture;
3798 // must start 0 so the first loadimagepixels has no requested width/height
3800 cubemappixels = NULL;
3801 cubemaptexture = NULL;
3802 // keep trying different suffix groups (posx, px, rt) until one loads
3803 for (j = 0;j < 3 && !cubemappixels;j++)
3805 // load the 6 images in the suffix group
3806 for (i = 0;i < 6;i++)
3808 // generate an image name based on the base and and suffix
3809 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3811 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3813 // an image loaded, make sure width and height are equal
3814 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3816 // if this is the first image to load successfully, allocate the cubemap memory
3817 if (!cubemappixels && image_width >= 1)
3819 cubemapsize = image_width;
3820 // note this clears to black, so unavailable sides are black
3821 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3823 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3825 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);
3828 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3830 Mem_Free(image_buffer);
3834 // if a cubemap loaded, upload it
3837 if (developer_loading.integer)
3838 Con_Printf("loading cubemap \"%s\"\n", basename);
3840 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer && gl_texturecompression.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3841 Mem_Free(cubemappixels);
3845 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3846 if (developer_loading.integer)
3848 Con_Printf("(tried tried images ");
3849 for (j = 0;j < 3;j++)
3850 for (i = 0;i < 6;i++)
3851 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3852 Con_Print(" and was unable to find any of them).\n");
3855 return cubemaptexture;
3858 rtexture_t *R_GetCubemap(const char *basename)
3861 for (i = 0;i < r_texture_numcubemaps;i++)
3862 if (r_texture_cubemaps[i] != NULL)
3863 if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3864 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3865 if (i >= MAX_CUBEMAPS || !r_main_mempool)
3866 return r_texture_whitecube;
3867 r_texture_numcubemaps++;
3868 r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3869 strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3870 r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3871 return r_texture_cubemaps[i]->texture;
3874 static void R_Main_FreeViewCache(void)
3876 if (r_refdef.viewcache.entityvisible)
3877 Mem_Free(r_refdef.viewcache.entityvisible);
3878 if (r_refdef.viewcache.world_pvsbits)
3879 Mem_Free(r_refdef.viewcache.world_pvsbits);
3880 if (r_refdef.viewcache.world_leafvisible)
3881 Mem_Free(r_refdef.viewcache.world_leafvisible);
3882 if (r_refdef.viewcache.world_surfacevisible)
3883 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3884 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3887 static void R_Main_ResizeViewCache(void)
3889 int numentities = r_refdef.scene.numentities;
3890 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3891 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3892 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3893 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3894 if (r_refdef.viewcache.maxentities < numentities)
3896 r_refdef.viewcache.maxentities = numentities;
3897 if (r_refdef.viewcache.entityvisible)
3898 Mem_Free(r_refdef.viewcache.entityvisible);
3899 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3901 if (r_refdef.viewcache.world_numclusters != numclusters)
3903 r_refdef.viewcache.world_numclusters = numclusters;
3904 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3905 if (r_refdef.viewcache.world_pvsbits)
3906 Mem_Free(r_refdef.viewcache.world_pvsbits);
3907 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3909 if (r_refdef.viewcache.world_numleafs != numleafs)
3911 r_refdef.viewcache.world_numleafs = numleafs;
3912 if (r_refdef.viewcache.world_leafvisible)
3913 Mem_Free(r_refdef.viewcache.world_leafvisible);
3914 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3916 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3918 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3919 if (r_refdef.viewcache.world_surfacevisible)
3920 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3921 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3925 extern rtexture_t *loadingscreentexture;
3926 static void gl_main_start(void)
3928 loadingscreentexture = NULL;
3929 r_texture_blanknormalmap = NULL;
3930 r_texture_white = NULL;
3931 r_texture_grey128 = NULL;
3932 r_texture_black = NULL;
3933 r_texture_whitecube = NULL;
3934 r_texture_normalizationcube = NULL;
3935 r_texture_fogattenuation = NULL;
3936 r_texture_fogheighttexture = NULL;
3937 r_texture_gammaramps = NULL;
3938 r_texture_numcubemaps = 0;
3940 r_loaddds = r_texture_dds_load.integer != 0;
3941 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3943 switch(vid.renderpath)
3945 case RENDERPATH_GL20:
3946 case RENDERPATH_D3D9:
3947 case RENDERPATH_D3D10:
3948 case RENDERPATH_D3D11:
3949 case RENDERPATH_SOFT:
3950 case RENDERPATH_GLES2:
3951 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3952 Cvar_SetValueQuick(&gl_combine, 1);
3953 Cvar_SetValueQuick(&r_glsl, 1);
3954 r_loadnormalmap = true;
3958 case RENDERPATH_GL13:
3959 case RENDERPATH_GLES1:
3960 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3961 Cvar_SetValueQuick(&gl_combine, 1);
3962 Cvar_SetValueQuick(&r_glsl, 0);
3963 r_loadnormalmap = false;
3964 r_loadgloss = false;
3967 case RENDERPATH_GL11:
3968 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3969 Cvar_SetValueQuick(&gl_combine, 0);
3970 Cvar_SetValueQuick(&r_glsl, 0);
3971 r_loadnormalmap = false;
3972 r_loadgloss = false;
3978 R_FrameData_Reset();
3982 memset(r_queries, 0, sizeof(r_queries));
3984 r_qwskincache = NULL;
3985 r_qwskincache_size = 0;
3987 // due to caching of texture_t references, the collision cache must be reset
3988 Collision_Cache_Reset(true);
3990 // set up r_skinframe loading system for textures
3991 memset(&r_skinframe, 0, sizeof(r_skinframe));
3992 r_skinframe.loadsequence = 1;
3993 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3995 r_main_texturepool = R_AllocTexturePool();
3996 R_BuildBlankTextures();
3998 if (vid.support.arb_texture_cube_map)
4001 R_BuildNormalizationCube();
4003 r_texture_fogattenuation = NULL;
4004 r_texture_fogheighttexture = NULL;
4005 r_texture_gammaramps = NULL;
4006 //r_texture_fogintensity = NULL;
4007 memset(&r_fb, 0, sizeof(r_fb));
4008 r_glsl_permutation = NULL;
4009 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4010 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4011 glslshaderstring = NULL;
4013 r_hlsl_permutation = NULL;
4014 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4015 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4017 hlslshaderstring = NULL;
4018 memset(&r_svbsp, 0, sizeof (r_svbsp));
4020 memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4021 r_texture_numcubemaps = 0;
4023 r_refdef.fogmasktable_density = 0;
4026 static void gl_main_shutdown(void)
4029 R_FrameData_Reset();
4031 R_Main_FreeViewCache();
4033 switch(vid.renderpath)
4035 case RENDERPATH_GL11:
4036 case RENDERPATH_GL13:
4037 case RENDERPATH_GL20:
4038 case RENDERPATH_GLES1:
4039 case RENDERPATH_GLES2:
4040 #ifdef GL_SAMPLES_PASSED_ARB
4042 qglDeleteQueriesARB(r_maxqueries, r_queries);
4045 case RENDERPATH_D3D9:
4046 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4048 case RENDERPATH_D3D10:
4049 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4051 case RENDERPATH_D3D11:
4052 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4054 case RENDERPATH_SOFT:
4060 memset(r_queries, 0, sizeof(r_queries));
4062 r_qwskincache = NULL;
4063 r_qwskincache_size = 0;
4065 // clear out the r_skinframe state
4066 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4067 memset(&r_skinframe, 0, sizeof(r_skinframe));
4070 Mem_Free(r_svbsp.nodes);
4071 memset(&r_svbsp, 0, sizeof (r_svbsp));
4072 R_FreeTexturePool(&r_main_texturepool);
4073 loadingscreentexture = NULL;
4074 r_texture_blanknormalmap = NULL;
4075 r_texture_white = NULL;
4076 r_texture_grey128 = NULL;
4077 r_texture_black = NULL;
4078 r_texture_whitecube = NULL;
4079 r_texture_normalizationcube = NULL;
4080 r_texture_fogattenuation = NULL;
4081 r_texture_fogheighttexture = NULL;
4082 r_texture_gammaramps = NULL;
4083 r_texture_numcubemaps = 0;
4084 //r_texture_fogintensity = NULL;
4085 memset(&r_fb, 0, sizeof(r_fb));
4088 r_glsl_permutation = NULL;
4089 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4090 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4091 glslshaderstring = NULL;
4093 r_hlsl_permutation = NULL;
4094 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4095 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4097 hlslshaderstring = NULL;
4100 static void gl_main_newmap(void)
4102 // FIXME: move this code to client
4103 char *entities, entname[MAX_QPATH];
4105 Mem_Free(r_qwskincache);
4106 r_qwskincache = NULL;
4107 r_qwskincache_size = 0;
4110 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4111 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4113 CL_ParseEntityLump(entities);
4117 if (cl.worldmodel->brush.entities)
4118 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4120 R_Main_FreeViewCache();
4122 R_FrameData_Reset();
4125 void GL_Main_Init(void)
4127 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4129 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4130 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4131 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4132 if (gamemode == GAME_NEHAHRA)
4134 Cvar_RegisterVariable (&gl_fogenable);
4135 Cvar_RegisterVariable (&gl_fogdensity);
4136 Cvar_RegisterVariable (&gl_fogred);
4137 Cvar_RegisterVariable (&gl_foggreen);
4138 Cvar_RegisterVariable (&gl_fogblue);
4139 Cvar_RegisterVariable (&gl_fogstart);
4140 Cvar_RegisterVariable (&gl_fogend);
4141 Cvar_RegisterVariable (&gl_skyclip);
4143 Cvar_RegisterVariable(&r_motionblur);
4144 Cvar_RegisterVariable(&r_damageblur);
4145 Cvar_RegisterVariable(&r_motionblur_averaging);
4146 Cvar_RegisterVariable(&r_motionblur_randomize);
4147 Cvar_RegisterVariable(&r_motionblur_minblur);
4148 Cvar_RegisterVariable(&r_motionblur_maxblur);
4149 Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4150 Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4151 Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4152 Cvar_RegisterVariable(&r_motionblur_mousefactor);
4153 Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4154 Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4155 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4156 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4157 Cvar_RegisterVariable(&r_equalize_entities_by);
4158 Cvar_RegisterVariable(&r_equalize_entities_to);
4159 Cvar_RegisterVariable(&r_depthfirst);
4160 Cvar_RegisterVariable(&r_useinfinitefarclip);
4161 Cvar_RegisterVariable(&r_farclip_base);
4162 Cvar_RegisterVariable(&r_farclip_world);
4163 Cvar_RegisterVariable(&r_nearclip);
4164 Cvar_RegisterVariable(&r_deformvertexes);
4165 Cvar_RegisterVariable(&r_transparent);
4166 Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4167 Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4168 Cvar_RegisterVariable(&r_transparent_useplanardistance);
4169 Cvar_RegisterVariable(&r_showoverdraw);
4170 Cvar_RegisterVariable(&r_showbboxes);
4171 Cvar_RegisterVariable(&r_showsurfaces);
4172 Cvar_RegisterVariable(&r_showtris);
4173 Cvar_RegisterVariable(&r_shownormals);
4174 Cvar_RegisterVariable(&r_showlighting);
4175 Cvar_RegisterVariable(&r_showshadowvolumes);
4176 Cvar_RegisterVariable(&r_showcollisionbrushes);
4177 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4178 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4179 Cvar_RegisterVariable(&r_showdisabledepthtest);
4180 Cvar_RegisterVariable(&r_drawportals);
4181 Cvar_RegisterVariable(&r_drawentities);
4182 Cvar_RegisterVariable(&r_draw2d);
4183 Cvar_RegisterVariable(&r_drawworld);
4184 Cvar_RegisterVariable(&r_cullentities_trace);
4185 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4186 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4187 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4188 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4189 Cvar_RegisterVariable(&r_sortentities);
4190 Cvar_RegisterVariable(&r_drawviewmodel);
4191 Cvar_RegisterVariable(&r_drawexteriormodel);
4192 Cvar_RegisterVariable(&r_speeds);
4193 Cvar_RegisterVariable(&r_fullbrights);
4194 Cvar_RegisterVariable(&r_wateralpha);
4195 Cvar_RegisterVariable(&r_dynamic);
4196 Cvar_RegisterVariable(&r_fakelight);
4197 Cvar_RegisterVariable(&r_fakelight_intensity);
4198 Cvar_RegisterVariable(&r_fullbright);
4199 Cvar_RegisterVariable(&r_shadows);
4200 Cvar_RegisterVariable(&r_shadows_darken);
4201 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4202 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4203 Cvar_RegisterVariable(&r_shadows_throwdistance);
4204 Cvar_RegisterVariable(&r_shadows_throwdirection);
4205 Cvar_RegisterVariable(&r_shadows_focus);
4206 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4207 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4208 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4209 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4210 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4211 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4212 Cvar_RegisterVariable(&r_fog_exp2);
4213 Cvar_RegisterVariable(&r_fog_clear);
4214 Cvar_RegisterVariable(&r_drawfog);
4215 Cvar_RegisterVariable(&r_transparentdepthmasking);
4216 Cvar_RegisterVariable(&r_transparent_sortmindist);
4217 Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4218 Cvar_RegisterVariable(&r_transparent_sortarraysize);
4219 Cvar_RegisterVariable(&r_texture_dds_load);
4220 Cvar_RegisterVariable(&r_texture_dds_save);
4221 Cvar_RegisterVariable(&r_textureunits);
4222 Cvar_RegisterVariable(&gl_combine);
4223 Cvar_RegisterVariable(&r_usedepthtextures);
4224 Cvar_RegisterVariable(&r_viewfbo);
4225 Cvar_RegisterVariable(&r_viewscale);
4226 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4227 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4228 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4229 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4230 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4231 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4232 Cvar_RegisterVariable(&r_glsl);
4233 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4234 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4235 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4236 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4237 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4238 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4239 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4240 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4241 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4242 Cvar_RegisterVariable(&r_glsl_postprocess);
4243 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4244 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4245 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4246 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4247 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4248 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4249 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4250 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4252 Cvar_RegisterVariable(&r_water);
4253 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4254 Cvar_RegisterVariable(&r_water_clippingplanebias);
4255 Cvar_RegisterVariable(&r_water_refractdistort);
4256 Cvar_RegisterVariable(&r_water_reflectdistort);
4257 Cvar_RegisterVariable(&r_water_scissormode);
4258 Cvar_RegisterVariable(&r_water_lowquality);
4259 Cvar_RegisterVariable(&r_water_hideplayer);
4260 Cvar_RegisterVariable(&r_water_fbo);
4262 Cvar_RegisterVariable(&r_lerpsprites);
4263 Cvar_RegisterVariable(&r_lerpmodels);
4264 Cvar_RegisterVariable(&r_lerplightstyles);
4265 Cvar_RegisterVariable(&r_waterscroll);
4266 Cvar_RegisterVariable(&r_bloom);
4267 Cvar_RegisterVariable(&r_bloom_colorscale);
4268 Cvar_RegisterVariable(&r_bloom_brighten);
4269 Cvar_RegisterVariable(&r_bloom_blur);
4270 Cvar_RegisterVariable(&r_bloom_resolution);
4271 Cvar_RegisterVariable(&r_bloom_colorexponent);
4272 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4273 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4274 Cvar_RegisterVariable(&r_hdr_glowintensity);
4275 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4276 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4277 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4278 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4279 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4280 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4281 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4282 Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4283 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4284 Cvar_RegisterVariable(&developer_texturelogging);
4285 Cvar_RegisterVariable(&gl_lightmaps);
4286 Cvar_RegisterVariable(&r_test);
4287 Cvar_RegisterVariable(&r_glsl_saturation);
4288 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4289 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4290 Cvar_RegisterVariable(&r_framedatasize);
4291 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4292 Cvar_SetValue("r_fullbrights", 0);
4293 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4296 void Render_Init(void)
4309 R_LightningBeams_Init();
4319 extern char *ENGINE_EXTENSIONS;
4322 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4323 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4324 gl_version = (const char *)qglGetString(GL_VERSION);
4325 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4329 if (!gl_platformextensions)
4330 gl_platformextensions = "";
4332 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4333 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4334 Con_Printf("GL_VERSION: %s\n", gl_version);
4335 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4336 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4338 VID_CheckExtensions();
4340 // LordHavoc: report supported extensions
4341 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4343 // clear to black (loading plaque will be seen over this)
4344 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4348 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4352 if (r_trippy.integer)
4354 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4356 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4359 p = r_refdef.view.frustum + i;
4364 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4368 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4372 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4376 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4380 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4384 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4388 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4392 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4400 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4404 if (r_trippy.integer)
4406 for (i = 0;i < numplanes;i++)
4413 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4417 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4421 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4425 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4429 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4433 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4437 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4441 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4449 //==================================================================================
4451 // LordHavoc: this stores temporary data used within the same frame
4453 typedef struct r_framedata_mem_s
4455 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4456 size_t size; // how much usable space
4457 size_t current; // how much space in use
4458 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4459 size_t wantedsize; // how much space was allocated
4460 unsigned char *data; // start of real data (16byte aligned)
4464 static r_framedata_mem_t *r_framedata_mem;
4466 void R_FrameData_Reset(void)
4468 while (r_framedata_mem)
4470 r_framedata_mem_t *next = r_framedata_mem->purge;
4471 Mem_Free(r_framedata_mem);
4472 r_framedata_mem = next;
4476 static void R_FrameData_Resize(void)
4479 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4480 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4481 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4483 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4484 newmem->wantedsize = wantedsize;
4485 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4486 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4487 newmem->current = 0;
4489 newmem->purge = r_framedata_mem;
4490 r_framedata_mem = newmem;
4494 void R_FrameData_NewFrame(void)
4496 R_FrameData_Resize();
4497 if (!r_framedata_mem)
4499 // if we ran out of space on the last frame, free the old memory now
4500 while (r_framedata_mem->purge)
4502 // repeatedly remove the second item in the list, leaving only head
4503 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4504 Mem_Free(r_framedata_mem->purge);
4505 r_framedata_mem->purge = next;
4507 // reset the current mem pointer
4508 r_framedata_mem->current = 0;
4509 r_framedata_mem->mark = 0;
4512 void *R_FrameData_Alloc(size_t size)
4516 // align to 16 byte boundary - the data pointer is already aligned, so we
4517 // only need to ensure the size of every allocation is also aligned
4518 size = (size + 15) & ~15;
4520 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4522 // emergency - we ran out of space, allocate more memory
4523 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4524 R_FrameData_Resize();
4527 data = r_framedata_mem->data + r_framedata_mem->current;
4528 r_framedata_mem->current += size;
4530 // count the usage for stats
4531 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4532 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4534 return (void *)data;
4537 void *R_FrameData_Store(size_t size, void *data)
4539 void *d = R_FrameData_Alloc(size);
4541 memcpy(d, data, size);
4545 void R_FrameData_SetMark(void)
4547 if (!r_framedata_mem)
4549 r_framedata_mem->mark = r_framedata_mem->current;
4552 void R_FrameData_ReturnToMark(void)
4554 if (!r_framedata_mem)
4556 r_framedata_mem->current = r_framedata_mem->mark;
4559 //==================================================================================
4561 // LordHavoc: animcache originally written by Echon, rewritten since then
4564 * Animation cache prevents re-generating mesh data for an animated model
4565 * multiple times in one frame for lighting, shadowing, reflections, etc.
4568 void R_AnimCache_Free(void)
4572 void R_AnimCache_ClearCache(void)
4575 entity_render_t *ent;
4577 for (i = 0;i < r_refdef.scene.numentities;i++)
4579 ent = r_refdef.scene.entities[i];
4580 ent->animcache_vertex3f = NULL;
4581 ent->animcache_normal3f = NULL;
4582 ent->animcache_svector3f = NULL;
4583 ent->animcache_tvector3f = NULL;
4584 ent->animcache_vertexmesh = NULL;
4585 ent->animcache_vertex3fbuffer = NULL;
4586 ent->animcache_vertexmeshbuffer = NULL;
4590 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4594 // check if we need the meshbuffers
4595 if (!vid.useinterleavedarrays)
4598 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4599 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4600 // TODO: upload vertex3f buffer?
4601 if (ent->animcache_vertexmesh)
4603 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4604 for (i = 0;i < numvertices;i++)
4605 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4606 if (ent->animcache_svector3f)
4607 for (i = 0;i < numvertices;i++)
4608 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4609 if (ent->animcache_tvector3f)
4610 for (i = 0;i < numvertices;i++)
4611 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4612 if (ent->animcache_normal3f)
4613 for (i = 0;i < numvertices;i++)
4614 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4615 // TODO: upload vertexmeshbuffer?
4619 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4621 dp_model_t *model = ent->model;
4623 // see if it's already cached this frame
4624 if (ent->animcache_vertex3f)
4626 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4627 if (wantnormals || wanttangents)
4629 if (ent->animcache_normal3f)
4630 wantnormals = false;
4631 if (ent->animcache_svector3f)
4632 wanttangents = false;
4633 if (wantnormals || wanttangents)
4635 numvertices = model->surfmesh.num_vertices;
4637 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4640 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4641 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4643 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4644 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4650 // see if this ent is worth caching
4651 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4653 // get some memory for this entity and generate mesh data
4654 numvertices = model->surfmesh.num_vertices;
4655 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4657 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4660 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4661 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4663 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4664 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4669 void R_AnimCache_CacheVisibleEntities(void)
4672 qboolean wantnormals = true;
4673 qboolean wanttangents = !r_showsurfaces.integer;
4675 switch(vid.renderpath)
4677 case RENDERPATH_GL20:
4678 case RENDERPATH_D3D9:
4679 case RENDERPATH_D3D10:
4680 case RENDERPATH_D3D11:
4681 case RENDERPATH_GLES2:
4683 case RENDERPATH_GL11:
4684 case RENDERPATH_GL13:
4685 case RENDERPATH_GLES1:
4686 wanttangents = false;
4688 case RENDERPATH_SOFT:
4692 if (r_shownormals.integer)
4693 wanttangents = wantnormals = true;
4695 // TODO: thread this
4696 // NOTE: R_PrepareRTLights() also caches entities
4698 for (i = 0;i < r_refdef.scene.numentities;i++)
4699 if (r_refdef.viewcache.entityvisible[i])
4700 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4703 //==================================================================================
4705 extern cvar_t r_overheadsprites_pushback;
4707 static void R_View_UpdateEntityLighting (void)
4710 entity_render_t *ent;
4711 vec3_t tempdiffusenormal, avg;
4712 vec_t f, fa, fd, fdd;
4713 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4715 for (i = 0;i < r_refdef.scene.numentities;i++)
4717 ent = r_refdef.scene.entities[i];
4719 // skip unseen models and models that updated by CSQC
4720 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen) || ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
4724 if (ent->model && (ent->model == cl.worldmodel || ent->model->brush.parentmodel == cl.worldmodel))
4726 // TODO: use modellight for r_ambient settings on world?
4727 VectorSet(ent->modellight_ambient, 0, 0, 0);
4728 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4729 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4733 // fetch the lighting from the worldmodel data
4734 VectorClear(ent->modellight_ambient);
4735 VectorClear(ent->modellight_diffuse);
4736 VectorClear(tempdiffusenormal);
4737 if (ent->flags & RENDER_LIGHT)
4740 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4742 // complete lightning for lit sprites
4743 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4744 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4746 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4747 org[2] = org[2] + r_overheadsprites_pushback.value;
4748 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4751 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4753 if(ent->flags & RENDER_EQUALIZE)
4755 // first fix up ambient lighting...
4756 if(r_equalize_entities_minambient.value > 0)
4758 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4761 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4762 if(fa < r_equalize_entities_minambient.value * fd)
4765 // fa'/fd' = minambient
4766 // fa'+0.25*fd' = fa+0.25*fd
4768 // fa' = fd' * minambient
4769 // fd'*(0.25+minambient) = fa+0.25*fd
4771 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4772 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4774 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4775 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
4776 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4777 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4782 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4784 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4785 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4789 // adjust brightness and saturation to target
4790 avg[0] = avg[1] = avg[2] = fa / f;
4791 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4792 avg[0] = avg[1] = avg[2] = fd / f;
4793 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4799 VectorSet(ent->modellight_ambient, 1, 1, 1);
4801 // move the light direction into modelspace coordinates for lighting code
4802 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4803 if(VectorLength2(ent->modellight_lightdir) == 0)
4804 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4805 VectorNormalize(ent->modellight_lightdir);
4809 #define MAX_LINEOFSIGHTTRACES 64
4811 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4814 vec3_t boxmins, boxmaxs;
4817 dp_model_t *model = r_refdef.scene.worldmodel;
4819 if (!model || !model->brush.TraceLineOfSight)
4822 // expand the box a little
4823 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4824 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4825 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4826 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4827 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4828 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4830 // return true if eye is inside enlarged box
4831 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4835 VectorCopy(eye, start);
4836 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4837 if (model->brush.TraceLineOfSight(model, start, end))
4840 // try various random positions
4841 for (i = 0;i < numsamples;i++)
4843 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4844 if (model->brush.TraceLineOfSight(model, start, end))
4852 static void R_View_UpdateEntityVisible (void)
4857 entity_render_t *ent;
4859 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4860 : r_fb.water.hideplayer ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4861 : (chase_active.integer || r_fb.water.renderingscene) ? RENDER_VIEWMODEL
4862 : RENDER_EXTERIORMODEL;
4863 if (!r_drawviewmodel.integer)
4864 renderimask |= RENDER_VIEWMODEL;
4865 if (!r_drawexteriormodel.integer)
4866 renderimask |= RENDER_EXTERIORMODEL;
4867 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4869 // worldmodel can check visibility
4870 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4871 for (i = 0;i < r_refdef.scene.numentities;i++)
4873 ent = r_refdef.scene.entities[i];
4874 if (!(ent->flags & renderimask))
4875 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)))
4876 if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_WORLDOBJECT | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
4877 r_refdef.viewcache.entityvisible[i] = true;
4882 // no worldmodel or it can't check visibility
4883 for (i = 0;i < r_refdef.scene.numentities;i++)
4885 ent = r_refdef.scene.entities[i];
4886 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));
4889 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4890 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4892 for (i = 0;i < r_refdef.scene.numentities;i++)
4894 if (!r_refdef.viewcache.entityvisible[i])
4896 ent = r_refdef.scene.entities[i];
4897 if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4899 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4901 continue; // temp entities do pvs only
4902 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4903 ent->last_trace_visibility = realtime;
4904 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4905 r_refdef.viewcache.entityvisible[i] = 0;
4911 /// only used if skyrendermasked, and normally returns false
4912 static int R_DrawBrushModelsSky (void)
4915 entity_render_t *ent;
4918 for (i = 0;i < r_refdef.scene.numentities;i++)
4920 if (!r_refdef.viewcache.entityvisible[i])
4922 ent = r_refdef.scene.entities[i];
4923 if (!ent->model || !ent->model->DrawSky)
4925 ent->model->DrawSky(ent);
4931 static void R_DrawNoModel(entity_render_t *ent);
4932 static void R_DrawModels(void)
4935 entity_render_t *ent;
4937 for (i = 0;i < r_refdef.scene.numentities;i++)
4939 if (!r_refdef.viewcache.entityvisible[i])
4941 ent = r_refdef.scene.entities[i];
4942 r_refdef.stats.entities++;
4944 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4947 Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4948 Con_Printf("R_DrawModels\n");
4949 Con_Printf("model %s O %f %f %f F %f %f %f L %f %f %f U %f %f %f\n", ent->model->name, o[0], o[1], o[2], f[0], f[1], f[2], l[0], l[1], l[2], u[0], u[1], u[2]);
4950 Con_Printf("group: %i %f %i %f %i %f %i %f\n", ent->framegroupblend[0].frame, ent->framegroupblend[0].lerp, ent->framegroupblend[1].frame, ent->framegroupblend[1].lerp, ent->framegroupblend[2].frame, ent->framegroupblend[2].lerp, ent->framegroupblend[3].frame, ent->framegroupblend[3].lerp);
4951 Con_Printf("blend: %i %f %i %f %i %f %i %f %i %f %i %f %i %f %i %f\n", ent->frameblend[0].subframe, ent->frameblend[0].lerp, ent->frameblend[1].subframe, ent->frameblend[1].lerp, ent->frameblend[2].subframe, ent->frameblend[2].lerp, ent->frameblend[3].subframe, ent->frameblend[3].lerp, ent->frameblend[4].subframe, ent->frameblend[4].lerp, ent->frameblend[5].subframe, ent->frameblend[5].lerp, ent->frameblend[6].subframe, ent->frameblend[6].lerp, ent->frameblend[7].subframe, ent->frameblend[7].lerp);
4954 if (ent->model && ent->model->Draw != NULL)
4955 ent->model->Draw(ent);
4961 static void R_DrawModelsDepth(void)
4964 entity_render_t *ent;
4966 for (i = 0;i < r_refdef.scene.numentities;i++)
4968 if (!r_refdef.viewcache.entityvisible[i])
4970 ent = r_refdef.scene.entities[i];
4971 if (ent->model && ent->model->DrawDepth != NULL)
4972 ent->model->DrawDepth(ent);
4976 static void R_DrawModelsDebug(void)
4979 entity_render_t *ent;
4981 for (i = 0;i < r_refdef.scene.numentities;i++)
4983 if (!r_refdef.viewcache.entityvisible[i])
4985 ent = r_refdef.scene.entities[i];
4986 if (ent->model && ent->model->DrawDebug != NULL)
4987 ent->model->DrawDebug(ent);
4991 static void R_DrawModelsAddWaterPlanes(void)
4994 entity_render_t *ent;
4996 for (i = 0;i < r_refdef.scene.numentities;i++)
4998 if (!r_refdef.viewcache.entityvisible[i])
5000 ent = r_refdef.scene.entities[i];
5001 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5002 ent->model->DrawAddWaterPlanes(ent);
5006 static float irisvecs[7][3] = {{0, 0, 0}, {-1, 0, 0}, {1, 0, 0}, {0, -1, 0}, {0, 1, 0}, {0, 0, -1}, {0, 0, 1}};
5008 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5010 if (r_hdr_irisadaptation.integer)
5015 vec3_t diffusenormal;
5017 vec_t brightness = 0.0f;
5022 VectorCopy(r_refdef.view.forward, forward);
5023 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5025 p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5026 p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5027 p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5028 R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5029 d = DotProduct(forward, diffusenormal);
5030 brightness += VectorLength(ambient);
5032 brightness += d * VectorLength(diffuse);
5034 brightness *= 1.0f / c;
5035 brightness += 0.00001f; // make sure it's never zero
5036 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5037 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5038 current = r_hdr_irisadaptation_value.value;
5040 current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5041 else if (current > goal)
5042 current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5043 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5044 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5046 else if (r_hdr_irisadaptation_value.value != 1.0f)
5047 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5050 static void R_View_SetFrustum(const int *scissor)
5053 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5054 vec3_t forward, left, up, origin, v;
5058 // flipped x coordinates (because x points left here)
5059 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5060 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5062 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5063 switch(vid.renderpath)
5065 case RENDERPATH_D3D9:
5066 case RENDERPATH_D3D10:
5067 case RENDERPATH_D3D11:
5068 // non-flipped y coordinates
5069 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5070 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5072 case RENDERPATH_SOFT:
5073 case RENDERPATH_GL11:
5074 case RENDERPATH_GL13:
5075 case RENDERPATH_GL20:
5076 case RENDERPATH_GLES1:
5077 case RENDERPATH_GLES2:
5078 // non-flipped y coordinates
5079 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5080 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5085 // we can't trust r_refdef.view.forward and friends in reflected scenes
5086 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5089 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5090 r_refdef.view.frustum[0].normal[1] = 0 - 0;
5091 r_refdef.view.frustum[0].normal[2] = -1 - 0;
5092 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5093 r_refdef.view.frustum[1].normal[1] = 0 + 0;
5094 r_refdef.view.frustum[1].normal[2] = -1 + 0;
5095 r_refdef.view.frustum[2].normal[0] = 0 - 0;
5096 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5097 r_refdef.view.frustum[2].normal[2] = -1 - 0;
5098 r_refdef.view.frustum[3].normal[0] = 0 + 0;
5099 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5100 r_refdef.view.frustum[3].normal[2] = -1 + 0;
5104 zNear = r_refdef.nearclip;
5105 nudge = 1.0 - 1.0 / (1<<23);
5106 r_refdef.view.frustum[4].normal[0] = 0 - 0;
5107 r_refdef.view.frustum[4].normal[1] = 0 - 0;
5108 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5109 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5110 r_refdef.view.frustum[5].normal[0] = 0 + 0;
5111 r_refdef.view.frustum[5].normal[1] = 0 + 0;
5112 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5113 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5119 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5120 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5121 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5122 r_refdef.view.frustum[0].dist = m[15] - m[12];
5124 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5125 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5126 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5127 r_refdef.view.frustum[1].dist = m[15] + m[12];
5129 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5130 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5131 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5132 r_refdef.view.frustum[2].dist = m[15] - m[13];
5134 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5135 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5136 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5137 r_refdef.view.frustum[3].dist = m[15] + m[13];
5139 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5140 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5141 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5142 r_refdef.view.frustum[4].dist = m[15] - m[14];
5144 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5145 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5146 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5147 r_refdef.view.frustum[5].dist = m[15] + m[14];
5150 if (r_refdef.view.useperspective)
5152 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5153 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]);
5154 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]);
5155 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]);
5156 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]);
5158 // then the normals from the corners relative to origin
5159 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5160 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5161 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5162 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5164 // in a NORMAL view, forward cross left == up
5165 // in a REFLECTED view, forward cross left == down
5166 // so our cross products above need to be adjusted for a left handed coordinate system
5167 CrossProduct(forward, left, v);
5168 if(DotProduct(v, up) < 0)
5170 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5171 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5172 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5173 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5176 // Leaving those out was a mistake, those were in the old code, and they
5177 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5178 // I couldn't reproduce it after adding those normalizations. --blub
5179 VectorNormalize(r_refdef.view.frustum[0].normal);
5180 VectorNormalize(r_refdef.view.frustum[1].normal);
5181 VectorNormalize(r_refdef.view.frustum[2].normal);
5182 VectorNormalize(r_refdef.view.frustum[3].normal);
5184 // make the corners absolute
5185 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5186 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5187 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5188 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5191 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5193 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5194 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5195 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5196 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5197 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5201 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5202 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5203 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5204 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5205 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5206 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5207 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5208 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5209 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5210 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5212 r_refdef.view.numfrustumplanes = 5;
5214 if (r_refdef.view.useclipplane)
5216 r_refdef.view.numfrustumplanes = 6;
5217 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5220 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5221 PlaneClassify(r_refdef.view.frustum + i);
5223 // LordHavoc: note to all quake engine coders, Quake had a special case
5224 // for 90 degrees which assumed a square view (wrong), so I removed it,
5225 // Quake2 has it disabled as well.
5227 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5228 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5229 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5230 //PlaneClassify(&frustum[0]);
5232 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5233 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5234 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5235 //PlaneClassify(&frustum[1]);
5237 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5238 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5239 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5240 //PlaneClassify(&frustum[2]);
5242 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5243 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5244 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5245 //PlaneClassify(&frustum[3]);
5248 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5249 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5250 //PlaneClassify(&frustum[4]);
5253 static void R_View_UpdateWithScissor(const int *myscissor)
5255 R_Main_ResizeViewCache();
5256 R_View_SetFrustum(myscissor);
5257 R_View_WorldVisibility(r_refdef.view.useclipplane);
5258 R_View_UpdateEntityVisible();
5259 R_View_UpdateEntityLighting();
5260 R_AnimCache_CacheVisibleEntities();
5263 static void R_View_Update(void)
5265 R_Main_ResizeViewCache();
5266 R_View_SetFrustum(NULL);
5267 R_View_WorldVisibility(r_refdef.view.useclipplane);
5268 R_View_UpdateEntityVisible();
5269 R_View_UpdateEntityLighting();
5270 R_AnimCache_CacheVisibleEntities();
5273 float viewscalefpsadjusted = 1.0f;
5275 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5277 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5278 scale = bound(0.03125f, scale, 1.0f);
5279 *outwidth = (int)ceil(width * scale);
5280 *outheight = (int)ceil(height * scale);
5283 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5285 const float *customclipplane = NULL;
5287 int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5288 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5290 // LordHavoc: couldn't figure out how to make this approach the
5291 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5292 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5293 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5294 dist = r_refdef.view.clipplane.dist;
5295 plane[0] = r_refdef.view.clipplane.normal[0];
5296 plane[1] = r_refdef.view.clipplane.normal[1];
5297 plane[2] = r_refdef.view.clipplane.normal[2];
5299 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5302 //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5303 rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5305 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5306 if (!r_refdef.view.useperspective)
5307 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - 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);
5308 else if (vid.stencil && r_useinfinitefarclip.integer)
5309 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
5311 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
5312 R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5313 R_SetViewport(&r_refdef.view.viewport);
5314 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5316 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5317 float screenplane[4];
5318 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5319 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5320 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5321 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5322 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5326 void R_EntityMatrix(const matrix4x4_t *matrix)
5328 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5330 gl_modelmatrixchanged = false;
5331 gl_modelmatrix = *matrix;
5332 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5333 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5334 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5335 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5337 switch(vid.renderpath)
5339 case RENDERPATH_D3D9:
5341 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5342 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5345 case RENDERPATH_D3D10:
5346 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5348 case RENDERPATH_D3D11:
5349 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5351 case RENDERPATH_GL11:
5352 case RENDERPATH_GL13:
5353 case RENDERPATH_GLES1:
5354 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5356 case RENDERPATH_SOFT:
5357 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5358 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5360 case RENDERPATH_GL20:
5361 case RENDERPATH_GLES2:
5362 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5363 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5369 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5371 r_viewport_t viewport;
5375 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5376 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, x2, y2, -10, 100, NULL);
5377 R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5378 R_SetViewport(&viewport);
5379 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5380 GL_Color(1, 1, 1, 1);
5381 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5382 GL_BlendFunc(GL_ONE, GL_ZERO);
5383 GL_ScissorTest(false);
5384 GL_DepthMask(false);
5385 GL_DepthRange(0, 1);
5386 GL_DepthTest(false);
5387 GL_DepthFunc(GL_LEQUAL);
5388 R_EntityMatrix(&identitymatrix);
5389 R_Mesh_ResetTextureState();
5390 GL_PolygonOffset(0, 0);
5391 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5392 switch(vid.renderpath)
5394 case RENDERPATH_GL11:
5395 case RENDERPATH_GL13:
5396 case RENDERPATH_GL20:
5397 case RENDERPATH_GLES1:
5398 case RENDERPATH_GLES2:
5399 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5401 case RENDERPATH_D3D9:
5402 case RENDERPATH_D3D10:
5403 case RENDERPATH_D3D11:
5404 case RENDERPATH_SOFT:
5407 GL_CullFace(GL_NONE);
5412 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5416 R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5419 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5423 R_SetupView(true, fbo, depthtexture, colortexture);
5424 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5425 GL_Color(1, 1, 1, 1);
5426 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5427 GL_BlendFunc(GL_ONE, GL_ZERO);
5428 GL_ScissorTest(true);
5430 GL_DepthRange(0, 1);
5432 GL_DepthFunc(GL_LEQUAL);
5433 R_EntityMatrix(&identitymatrix);
5434 R_Mesh_ResetTextureState();
5435 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5436 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5437 switch(vid.renderpath)
5439 case RENDERPATH_GL11:
5440 case RENDERPATH_GL13:
5441 case RENDERPATH_GL20:
5442 case RENDERPATH_GLES1:
5443 case RENDERPATH_GLES2:
5444 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5446 case RENDERPATH_D3D9:
5447 case RENDERPATH_D3D10:
5448 case RENDERPATH_D3D11:
5449 case RENDERPATH_SOFT:
5452 GL_CullFace(r_refdef.view.cullface_back);
5457 R_RenderView_UpdateViewVectors
5460 void R_RenderView_UpdateViewVectors(void)
5462 // break apart the view matrix into vectors for various purposes
5463 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5464 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5465 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5466 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5467 // make an inverted copy of the view matrix for tracking sprites
5468 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5471 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5472 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5474 static void R_Water_StartFrame(void)
5477 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5478 r_waterstate_waterplane_t *p;
5479 qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.samples < 2;
5481 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5484 switch(vid.renderpath)
5486 case RENDERPATH_GL20:
5487 case RENDERPATH_D3D9:
5488 case RENDERPATH_D3D10:
5489 case RENDERPATH_D3D11:
5490 case RENDERPATH_SOFT:
5491 case RENDERPATH_GLES2:
5493 case RENDERPATH_GL11:
5494 case RENDERPATH_GL13:
5495 case RENDERPATH_GLES1:
5499 // set waterwidth and waterheight to the water resolution that will be
5500 // used (often less than the screen resolution for faster rendering)
5501 R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5503 // calculate desired texture sizes
5504 // can't use water if the card does not support the texture size
5505 if (!r_water.integer || r_showsurfaces.integer)
5506 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5507 else if (vid.support.arb_texture_non_power_of_two)
5509 texturewidth = waterwidth;
5510 textureheight = waterheight;
5511 camerawidth = waterwidth;
5512 cameraheight = waterheight;
5516 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5517 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5518 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5519 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5522 // allocate textures as needed
5523 if (r_fb.water.texturewidth != texturewidth || r_fb.water.textureheight != textureheight || r_fb.water.camerawidth != camerawidth || r_fb.water.cameraheight != cameraheight || (r_fb.depthtexture && !usewaterfbo))
5525 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5526 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5528 if (p->texture_refraction)
5529 R_FreeTexture(p->texture_refraction);
5530 p->texture_refraction = NULL;
5531 if (p->fbo_refraction)
5532 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5533 p->fbo_refraction = 0;
5534 if (p->texture_reflection)
5535 R_FreeTexture(p->texture_reflection);
5536 p->texture_reflection = NULL;
5537 if (p->fbo_reflection)
5538 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5539 p->fbo_reflection = 0;
5540 if (p->texture_camera)
5541 R_FreeTexture(p->texture_camera);
5542 p->texture_camera = NULL;
5544 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5547 memset(&r_fb.water, 0, sizeof(r_fb.water));
5548 r_fb.water.texturewidth = texturewidth;
5549 r_fb.water.textureheight = textureheight;
5550 r_fb.water.camerawidth = camerawidth;
5551 r_fb.water.cameraheight = cameraheight;
5554 if (r_fb.water.texturewidth)
5556 int scaledwidth, scaledheight;
5558 r_fb.water.enabled = true;
5560 // water resolution is usually reduced
5561 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5562 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5563 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5565 // set up variables that will be used in shader setup
5566 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5567 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5568 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5569 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5572 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5573 r_fb.water.numwaterplanes = 0;
5576 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5578 int planeindex, bestplaneindex, vertexindex;
5579 vec3_t mins, maxs, normal, center, v, n;
5580 vec_t planescore, bestplanescore;
5582 r_waterstate_waterplane_t *p;
5583 texture_t *t = R_GetCurrentTexture(surface->texture);
5585 rsurface.texture = t;
5586 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5587 // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5588 if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5590 // average the vertex normals, find the surface bounds (after deformvertexes)
5591 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5592 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5593 VectorCopy(n, normal);
5594 VectorCopy(v, mins);
5595 VectorCopy(v, maxs);
5596 for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5598 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5599 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5600 VectorAdd(normal, n, normal);
5601 mins[0] = min(mins[0], v[0]);
5602 mins[1] = min(mins[1], v[1]);
5603 mins[2] = min(mins[2], v[2]);
5604 maxs[0] = max(maxs[0], v[0]);
5605 maxs[1] = max(maxs[1], v[1]);
5606 maxs[2] = max(maxs[2], v[2]);
5608 VectorNormalize(normal);
5609 VectorMAM(0.5f, mins, 0.5f, maxs, center);
5611 VectorCopy(normal, plane.normal);
5612 VectorNormalize(plane.normal);
5613 plane.dist = DotProduct(center, plane.normal);
5614 PlaneClassify(&plane);
5615 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5617 // skip backfaces (except if nocullface is set)
5618 // if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5620 VectorNegate(plane.normal, plane.normal);
5622 PlaneClassify(&plane);
5626 // find a matching plane if there is one
5627 bestplaneindex = -1;
5628 bestplanescore = 1048576.0f;
5629 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5631 if(p->camera_entity == t->camera_entity)
5633 planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5634 if (bestplaneindex < 0 || bestplanescore > planescore)
5636 bestplaneindex = planeindex;
5637 bestplanescore = planescore;
5641 planeindex = bestplaneindex;
5642 p = r_fb.water.waterplanes + planeindex;
5644 // if this surface does not fit any known plane rendered this frame, add one
5645 if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5647 // store the new plane
5648 planeindex = r_fb.water.numwaterplanes++;
5649 p = r_fb.water.waterplanes + planeindex;
5651 // clear materialflags and pvs
5652 p->materialflags = 0;
5653 p->pvsvalid = false;
5654 p->camera_entity = t->camera_entity;
5655 VectorCopy(mins, p->mins);
5656 VectorCopy(maxs, p->maxs);
5660 // merge mins/maxs when we're adding this surface to the plane
5661 p->mins[0] = min(p->mins[0], mins[0]);
5662 p->mins[1] = min(p->mins[1], mins[1]);
5663 p->mins[2] = min(p->mins[2], mins[2]);
5664 p->maxs[0] = max(p->maxs[0], maxs[0]);
5665 p->maxs[1] = max(p->maxs[1], maxs[1]);
5666 p->maxs[2] = max(p->maxs[2], maxs[2]);
5668 // merge this surface's materialflags into the waterplane
5669 p->materialflags |= t->currentmaterialflags;
5670 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5672 // merge this surface's PVS into the waterplane
5673 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5674 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5676 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5682 extern cvar_t r_drawparticles;
5683 extern cvar_t r_drawdecals;
5685 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5688 r_refdef_view_t originalview;
5689 r_refdef_view_t myview;
5690 int planeindex, qualityreduction = 0, old_r_dynamic = 0, old_r_shadows = 0, old_r_worldrtlight = 0, old_r_dlight = 0, old_r_particles = 0, old_r_decals = 0;
5691 r_waterstate_waterplane_t *p;
5693 qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.samples < 2;
5696 originalview = r_refdef.view;
5698 // lowquality hack, temporarily shut down some cvars and restore afterwards
5699 qualityreduction = r_water_lowquality.integer;
5700 if (qualityreduction > 0)
5702 if (qualityreduction >= 1)
5704 old_r_shadows = r_shadows.integer;
5705 old_r_worldrtlight = r_shadow_realtime_world.integer;
5706 old_r_dlight = r_shadow_realtime_dlight.integer;
5707 Cvar_SetValueQuick(&r_shadows, 0);
5708 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5709 Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5711 if (qualityreduction >= 2)
5713 old_r_dynamic = r_dynamic.integer;
5714 old_r_particles = r_drawparticles.integer;
5715 old_r_decals = r_drawdecals.integer;
5716 Cvar_SetValueQuick(&r_dynamic, 0);
5717 Cvar_SetValueQuick(&r_drawparticles, 0);
5718 Cvar_SetValueQuick(&r_drawdecals, 0);
5722 // make sure enough textures are allocated
5723 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5725 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5727 if (!p->texture_refraction)
5728 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_refraction", planeindex), r_fb.water.texturewidth, r_fb.water.textureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5729 if (!p->texture_refraction)
5733 if (r_fb.water.depthtexture == NULL)
5734 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5735 if (p->fbo_refraction == 0)
5736 p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
5739 else if (p->materialflags & MATERIALFLAG_CAMERA)
5741 if (!p->texture_camera)
5742 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_camera", planeindex), r_fb.water.camerawidth, r_fb.water.cameraheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR, -1, NULL);
5743 if (!p->texture_camera)
5747 if (r_fb.water.depthtexture == NULL)
5748 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5749 if (p->fbo_camera == 0)
5750 p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
5754 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5756 if (!p->texture_reflection)
5757 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_reflection", planeindex), r_fb.water.texturewidth, r_fb.water.textureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5758 if (!p->texture_reflection)
5762 if (r_fb.water.depthtexture == NULL)
5763 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5764 if (p->fbo_reflection == 0)
5765 p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
5771 r_refdef.view = originalview;
5772 r_refdef.view.showdebug = false;
5773 r_refdef.view.width = r_fb.water.waterwidth;
5774 r_refdef.view.height = r_fb.water.waterheight;
5775 r_refdef.view.useclipplane = true;
5776 myview = r_refdef.view;
5777 r_fb.water.renderingscene = true;
5778 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5780 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5782 r_refdef.view = myview;
5783 if(r_water_scissormode.integer)
5785 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5786 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5787 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5790 // render reflected scene and copy into texture
5791 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5792 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5793 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5794 r_refdef.view.clipplane = p->plane;
5795 // reverse the cullface settings for this render
5796 r_refdef.view.cullface_front = GL_FRONT;
5797 r_refdef.view.cullface_back = GL_BACK;
5798 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5800 r_refdef.view.usecustompvs = true;
5802 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5804 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5807 r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
5808 R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5809 R_ClearScreen(r_refdef.fogenabled);
5810 if(r_water_scissormode.integer & 2)
5811 R_View_UpdateWithScissor(myscissor);
5814 if(r_water_scissormode.integer & 1)
5815 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5816 R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5818 if (!p->fbo_reflection)
5819 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);
5820 r_fb.water.hideplayer = false;
5823 // render the normal view scene and copy into texture
5824 // (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)
5825 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5827 r_refdef.view = myview;
5828 if(r_water_scissormode.integer)
5830 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5831 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5832 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5835 r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
5837 r_refdef.view.clipplane = p->plane;
5838 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5839 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5841 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5843 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5844 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
5845 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5846 R_RenderView_UpdateViewVectors();
5847 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5849 r_refdef.view.usecustompvs = true;
5850 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);
5854 PlaneClassify(&r_refdef.view.clipplane);
5856 R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5857 R_ClearScreen(r_refdef.fogenabled);
5858 if(r_water_scissormode.integer & 2)
5859 R_View_UpdateWithScissor(myscissor);
5862 if(r_water_scissormode.integer & 1)
5863 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5864 R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5866 if (!p->fbo_refraction)
5867 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);
5868 r_fb.water.hideplayer = false;
5870 else if (p->materialflags & MATERIALFLAG_CAMERA)
5872 r_refdef.view = myview;
5874 r_refdef.view.clipplane = p->plane;
5875 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5876 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5878 r_refdef.view.width = r_fb.water.camerawidth;
5879 r_refdef.view.height = r_fb.water.cameraheight;
5880 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5881 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5882 r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
5883 r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
5885 if(p->camera_entity)
5887 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5888 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5891 // note: all of the view is used for displaying... so
5892 // there is no use in scissoring
5894 // reverse the cullface settings for this render
5895 r_refdef.view.cullface_front = GL_FRONT;
5896 r_refdef.view.cullface_back = GL_BACK;
5897 // also reverse the view matrix
5898 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
5899 R_RenderView_UpdateViewVectors();
5900 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5902 r_refdef.view.usecustompvs = true;
5903 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);
5906 // camera needs no clipplane
5907 r_refdef.view.useclipplane = false;
5909 PlaneClassify(&r_refdef.view.clipplane);
5911 r_fb.water.hideplayer = false;
5913 R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
5914 R_ClearScreen(r_refdef.fogenabled);
5916 R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
5919 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);
5920 r_fb.water.hideplayer = false;
5924 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5925 r_fb.water.renderingscene = false;
5926 r_refdef.view = originalview;
5927 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
5928 if (!r_fb.water.depthtexture)
5929 R_ClearScreen(r_refdef.fogenabled);
5933 r_refdef.view = originalview;
5934 r_fb.water.renderingscene = false;
5935 Cvar_SetValueQuick(&r_water, 0);
5936 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5938 // lowquality hack, restore cvars
5939 if (qualityreduction > 0)
5941 if (qualityreduction >= 1)
5943 Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5944 Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5945 Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5947 if (qualityreduction >= 2)
5949 Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5950 Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5951 Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5956 static void R_Bloom_StartFrame(void)
5959 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5960 int viewwidth, viewheight;
5961 qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.samples < 2;
5962 textype_t textype = TEXTYPE_COLORBUFFER;
5964 switch (vid.renderpath)
5966 case RENDERPATH_GL20:
5967 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
5968 if (vid.support.ext_framebuffer_object)
5970 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5971 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5974 case RENDERPATH_GL11:
5975 case RENDERPATH_GL13:
5976 case RENDERPATH_GLES1:
5977 case RENDERPATH_GLES2:
5978 case RENDERPATH_D3D9:
5979 case RENDERPATH_D3D10:
5980 case RENDERPATH_D3D11:
5981 r_fb.usedepthtextures = false;
5983 case RENDERPATH_SOFT:
5984 r_fb.usedepthtextures = true;
5988 if (r_viewscale_fpsscaling.integer)
5990 double actualframetime;
5991 double targetframetime;
5993 actualframetime = r_refdef.lastdrawscreentime;
5994 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5995 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5996 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5997 if (r_viewscale_fpsscaling_stepsize.value > 0)
5998 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5999 viewscalefpsadjusted += adjust;
6000 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6003 viewscalefpsadjusted = 1.0f;
6005 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6007 switch(vid.renderpath)
6009 case RENDERPATH_GL20:
6010 case RENDERPATH_D3D9:
6011 case RENDERPATH_D3D10:
6012 case RENDERPATH_D3D11:
6013 case RENDERPATH_SOFT:
6014 case RENDERPATH_GLES2:
6016 case RENDERPATH_GL11:
6017 case RENDERPATH_GL13:
6018 case RENDERPATH_GLES1:
6022 // set bloomwidth and bloomheight to the bloom resolution that will be
6023 // used (often less than the screen resolution for faster rendering)
6024 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
6025 r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6026 r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6027 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6028 r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6030 // calculate desired texture sizes
6031 if (vid.support.arb_texture_non_power_of_two)
6033 screentexturewidth = vid.width;
6034 screentextureheight = vid.height;
6035 bloomtexturewidth = r_fb.bloomwidth;
6036 bloomtextureheight = r_fb.bloomheight;
6040 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
6041 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
6042 for (bloomtexturewidth = 1;bloomtexturewidth < r_fb.bloomwidth ;bloomtexturewidth *= 2);
6043 for (bloomtextureheight = 1;bloomtextureheight < r_fb.bloomheight;bloomtextureheight *= 2);
6046 if ((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))
6048 Cvar_SetValueQuick(&r_bloom, 0);
6049 Cvar_SetValueQuick(&r_motionblur, 0);
6050 Cvar_SetValueQuick(&r_damageblur, 0);
6053 if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6055 && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6057 && r_viewscale.value == 1.0f
6058 && !r_viewscale_fpsscaling.integer)
6059 screentexturewidth = screentextureheight = 0;
6060 if (!r_bloom.integer)
6061 bloomtexturewidth = bloomtextureheight = 0;
6063 // allocate textures as needed
6064 if (r_fb.screentexturewidth != screentexturewidth
6065 || r_fb.screentextureheight != screentextureheight
6066 || r_fb.bloomtexturewidth != bloomtexturewidth
6067 || r_fb.bloomtextureheight != bloomtextureheight
6068 || r_fb.textype != textype
6069 || useviewfbo != (r_fb.fbo != 0))
6071 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6073 if (r_fb.bloomtexture[i])
6074 R_FreeTexture(r_fb.bloomtexture[i]);
6075 r_fb.bloomtexture[i] = NULL;
6077 if (r_fb.bloomfbo[i])
6078 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6079 r_fb.bloomfbo[i] = 0;
6083 R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6086 if (r_fb.colortexture)
6087 R_FreeTexture(r_fb.colortexture);
6088 r_fb.colortexture = NULL;
6090 if (r_fb.depthtexture)
6091 R_FreeTexture(r_fb.depthtexture);
6092 r_fb.depthtexture = NULL;
6094 if (r_fb.ghosttexture)
6095 R_FreeTexture(r_fb.ghosttexture);
6096 r_fb.ghosttexture = NULL;
6098 r_fb.screentexturewidth = screentexturewidth;
6099 r_fb.screentextureheight = screentextureheight;
6100 r_fb.bloomtexturewidth = bloomtexturewidth;
6101 r_fb.bloomtextureheight = bloomtextureheight;
6102 r_fb.textype = textype;
6104 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6106 if (r_motionblur.value > 0 || r_damageblur.value > 0)
6107 r_fb.ghosttexture = R_LoadTexture2D(r_main_texturepool, "framebuffermotionblur", r_fb.screentexturewidth, r_fb.screentextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6108 r_fb.ghosttexture_valid = false;
6109 r_fb.colortexture = R_LoadTexture2D(r_main_texturepool, "framebuffercolor", r_fb.screentexturewidth, r_fb.screentextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6112 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6113 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6114 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6118 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6120 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6122 r_fb.bloomtexture[i] = R_LoadTexture2D(r_main_texturepool, "framebufferbloom", r_fb.bloomtexturewidth, r_fb.bloomtextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6124 r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6129 // bloom texture is a different resolution
6130 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6131 r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6132 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6133 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6134 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6136 // set up a texcoord array for the full resolution screen image
6137 // (we have to keep this around to copy back during final render)
6138 r_fb.screentexcoord2f[0] = 0;
6139 r_fb.screentexcoord2f[1] = (float)viewheight / (float)r_fb.screentextureheight;
6140 r_fb.screentexcoord2f[2] = (float)viewwidth / (float)r_fb.screentexturewidth;
6141 r_fb.screentexcoord2f[3] = (float)viewheight / (float)r_fb.screentextureheight;
6142 r_fb.screentexcoord2f[4] = (float)viewwidth / (float)r_fb.screentexturewidth;
6143 r_fb.screentexcoord2f[5] = 0;
6144 r_fb.screentexcoord2f[6] = 0;
6145 r_fb.screentexcoord2f[7] = 0;
6147 // set up a texcoord array for the reduced resolution bloom image
6148 // (which will be additive blended over the screen image)
6149 r_fb.bloomtexcoord2f[0] = 0;
6150 r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6151 r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6152 r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6153 r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6154 r_fb.bloomtexcoord2f[5] = 0;
6155 r_fb.bloomtexcoord2f[6] = 0;
6156 r_fb.bloomtexcoord2f[7] = 0;
6158 switch(vid.renderpath)
6160 case RENDERPATH_GL11:
6161 case RENDERPATH_GL13:
6162 case RENDERPATH_GL20:
6163 case RENDERPATH_SOFT:
6164 case RENDERPATH_GLES1:
6165 case RENDERPATH_GLES2:
6167 case RENDERPATH_D3D9:
6168 case RENDERPATH_D3D10:
6169 case RENDERPATH_D3D11:
6172 for (i = 0;i < 4;i++)
6174 r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6175 r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6176 r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6177 r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6183 R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, r_refdef.view.x, (r_fb.bloomfbo[0] ? r_fb.bloomtextureheight : vid.height) - r_fb.bloomheight - r_refdef.view.y, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6186 r_refdef.view.clear = true;
6189 static void R_Bloom_MakeTexture(void)
6192 float xoffset, yoffset, r, brighten;
6194 float colorscale = r_bloom_colorscale.value;
6196 r_refdef.stats.bloom++;
6200 R_Mesh_CopyToTexture(r_fb.colortexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6201 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6204 // scale down screen texture to the bloom texture size
6206 r_fb.bloomindex = 0;
6207 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6208 R_SetViewport(&r_fb.bloomviewport);
6209 GL_BlendFunc(GL_ONE, GL_ZERO);
6210 GL_Color(colorscale, colorscale, colorscale, 1);
6211 // 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...
6212 switch(vid.renderpath)
6214 case RENDERPATH_GL11:
6215 case RENDERPATH_GL13:
6216 case RENDERPATH_GL20:
6217 case RENDERPATH_GLES1:
6218 case RENDERPATH_GLES2:
6219 case RENDERPATH_SOFT:
6220 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6222 case RENDERPATH_D3D9:
6223 case RENDERPATH_D3D10:
6224 case RENDERPATH_D3D11:
6225 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6228 // TODO: do boxfilter scale-down in shader?
6229 R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6230 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6231 r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6233 // we now have a properly scaled bloom image
6234 if (!r_fb.bloomfbo[r_fb.bloomindex])
6236 // copy it into the bloom texture
6237 R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
6238 r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6241 // multiply bloom image by itself as many times as desired
6242 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6244 intex = r_fb.bloomtexture[r_fb.bloomindex];
6245 r_fb.bloomindex ^= 1;
6246 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6248 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6249 if (!r_fb.bloomfbo[r_fb.bloomindex])
6251 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6252 GL_Color(r,r,r,1); // apply fix factor
6257 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6258 GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6259 GL_Color(1,1,1,1); // no fix factor supported here
6261 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6262 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6263 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6264 r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6266 if (!r_fb.bloomfbo[r_fb.bloomindex])
6268 // copy the darkened image to a texture
6269 R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
6270 r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6274 range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6275 brighten = r_bloom_brighten.value;
6276 brighten = sqrt(brighten);
6278 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6280 for (dir = 0;dir < 2;dir++)
6282 intex = r_fb.bloomtexture[r_fb.bloomindex];
6283 r_fb.bloomindex ^= 1;
6284 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6285 // blend on at multiple vertical offsets to achieve a vertical blur
6286 // TODO: do offset blends using GLSL
6287 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6288 GL_BlendFunc(GL_ONE, GL_ZERO);
6289 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6290 for (x = -range;x <= range;x++)
6292 if (!dir){xoffset = 0;yoffset = x;}
6293 else {xoffset = x;yoffset = 0;}
6294 xoffset /= (float)r_fb.bloomtexturewidth;
6295 yoffset /= (float)r_fb.bloomtextureheight;
6296 // compute a texcoord array with the specified x and y offset
6297 r_fb.offsettexcoord2f[0] = xoffset+0;
6298 r_fb.offsettexcoord2f[1] = yoffset+(float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6299 r_fb.offsettexcoord2f[2] = xoffset+(float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6300 r_fb.offsettexcoord2f[3] = yoffset+(float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6301 r_fb.offsettexcoord2f[4] = xoffset+(float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6302 r_fb.offsettexcoord2f[5] = yoffset+0;
6303 r_fb.offsettexcoord2f[6] = xoffset+0;
6304 r_fb.offsettexcoord2f[7] = yoffset+0;
6305 // this r value looks like a 'dot' particle, fading sharply to
6306 // black at the edges
6307 // (probably not realistic but looks good enough)
6308 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6309 //r = brighten/(range*2+1);
6310 r = brighten / (range * 2 + 1);
6312 r *= (1 - x*x/(float)(range*range));
6313 GL_Color(r, r, r, 1);
6314 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6315 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6316 r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6317 GL_BlendFunc(GL_ONE, GL_ONE);
6320 if (!r_fb.bloomfbo[r_fb.bloomindex])
6322 // copy the vertically or horizontally blurred bloom view to a texture
6323 R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
6324 r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6329 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6331 unsigned int permutation;
6332 float uservecs[4][4];
6334 switch (vid.renderpath)
6336 case RENDERPATH_GL20:
6337 case RENDERPATH_D3D9:
6338 case RENDERPATH_D3D10:
6339 case RENDERPATH_D3D11:
6340 case RENDERPATH_SOFT:
6341 case RENDERPATH_GLES2:
6343 (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6344 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6345 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6346 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6347 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6349 if (r_fb.colortexture)
6353 R_Mesh_CopyToTexture(r_fb.colortexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6354 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6357 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6359 // declare variables
6360 float blur_factor, blur_mouseaccel, blur_velocity;
6361 static float blur_average;
6362 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6364 // set a goal for the factoring
6365 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value)
6366 / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6367 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value)
6368 / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6369 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value)
6370 + (blur_mouseaccel * r_motionblur_mousefactor.value));
6372 // from the goal, pick an averaged value between goal and last value
6373 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6374 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6376 // enforce minimum amount of blur
6377 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6379 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6381 // calculate values into a standard alpha
6382 cl.motionbluralpha = 1 - exp(-
6384 (r_motionblur.value * blur_factor / 80)
6386 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6389 max(0.0001, cl.time - cl.oldtime) // fps independent
6392 // randomization for the blur value to combat persistent ghosting
6393 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6394 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6397 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6398 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6400 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6401 GL_Color(1, 1, 1, cl.motionbluralpha);
6402 switch(vid.renderpath)
6404 case RENDERPATH_GL11:
6405 case RENDERPATH_GL13:
6406 case RENDERPATH_GL20:
6407 case RENDERPATH_GLES1:
6408 case RENDERPATH_GLES2:
6409 case RENDERPATH_SOFT:
6410 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6412 case RENDERPATH_D3D9:
6413 case RENDERPATH_D3D10:
6414 case RENDERPATH_D3D11:
6415 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6418 R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6419 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6420 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6423 // updates old view angles for next pass
6424 VectorCopy(cl.viewangles, blur_oldangles);
6426 // copy view into the ghost texture
6427 R_Mesh_CopyToTexture(r_fb.ghosttexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6428 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6429 r_fb.ghosttexture_valid = true;
6434 // no r_fb.colortexture means we're rendering to the real fb
6435 // we may still have to do view tint...
6436 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6438 // apply a color tint to the whole view
6439 R_ResetViewRendering2D(0, NULL, NULL);
6440 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6441 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6442 R_SetupShader_Generic_NoTexture(false, true);
6443 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6444 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6446 break; // no screen processing, no bloom, skip it
6449 if (r_fb.bloomtexture[0])
6451 // make the bloom texture
6452 R_Bloom_MakeTexture();
6455 #if _MSC_VER >= 1400
6456 #define sscanf sscanf_s
6458 memset(uservecs, 0, sizeof(uservecs));
6459 if (r_glsl_postprocess_uservec1_enable.integer)
6460 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6461 if (r_glsl_postprocess_uservec2_enable.integer)
6462 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6463 if (r_glsl_postprocess_uservec3_enable.integer)
6464 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6465 if (r_glsl_postprocess_uservec4_enable.integer)
6466 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6468 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6469 GL_Color(1, 1, 1, 1);
6470 GL_BlendFunc(GL_ONE, GL_ZERO);
6472 switch(vid.renderpath)
6474 case RENDERPATH_GL20:
6475 case RENDERPATH_GLES2:
6476 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6477 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6478 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_fb.colortexture);
6479 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_fb.bloomtexture[r_fb.bloomindex]);
6480 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6481 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]);
6482 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6483 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]);
6484 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]);
6485 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]);
6486 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]);
6487 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6488 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6489 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);
6491 case RENDERPATH_D3D9:
6493 // 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...
6494 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6495 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6496 R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture);
6497 R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]);
6498 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6499 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6500 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6501 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6502 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6503 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6504 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6505 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6506 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6507 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6510 case RENDERPATH_D3D10:
6511 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6513 case RENDERPATH_D3D11:
6514 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6516 case RENDERPATH_SOFT:
6517 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6518 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6519 R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture);
6520 R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]);
6521 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6522 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6523 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6524 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6525 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6526 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6527 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6528 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6529 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6530 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6535 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6536 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6538 case RENDERPATH_GL11:
6539 case RENDERPATH_GL13:
6540 case RENDERPATH_GLES1:
6541 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6543 // apply a color tint to the whole view
6544 R_ResetViewRendering2D(0, NULL, NULL);
6545 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6546 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6547 R_SetupShader_Generic_NoTexture(false, true);
6548 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6549 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6555 matrix4x4_t r_waterscrollmatrix;
6557 void R_UpdateFog(void)
6560 if (gamemode == GAME_NEHAHRA)
6562 if (gl_fogenable.integer)
6564 r_refdef.oldgl_fogenable = true;
6565 r_refdef.fog_density = gl_fogdensity.value;
6566 r_refdef.fog_red = gl_fogred.value;
6567 r_refdef.fog_green = gl_foggreen.value;
6568 r_refdef.fog_blue = gl_fogblue.value;
6569 r_refdef.fog_alpha = 1;
6570 r_refdef.fog_start = 0;
6571 r_refdef.fog_end = gl_skyclip.value;
6572 r_refdef.fog_height = 1<<30;
6573 r_refdef.fog_fadedepth = 128;
6575 else if (r_refdef.oldgl_fogenable)
6577 r_refdef.oldgl_fogenable = false;
6578 r_refdef.fog_density = 0;
6579 r_refdef.fog_red = 0;
6580 r_refdef.fog_green = 0;
6581 r_refdef.fog_blue = 0;
6582 r_refdef.fog_alpha = 0;
6583 r_refdef.fog_start = 0;
6584 r_refdef.fog_end = 0;
6585 r_refdef.fog_height = 1<<30;
6586 r_refdef.fog_fadedepth = 128;
6591 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6592 r_refdef.fog_start = max(0, r_refdef.fog_start);
6593 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6595 if (r_refdef.fog_density && r_drawfog.integer)
6597 r_refdef.fogenabled = true;
6598 // this is the point where the fog reaches 0.9986 alpha, which we
6599 // consider a good enough cutoff point for the texture
6600 // (0.9986 * 256 == 255.6)
6601 if (r_fog_exp2.integer)
6602 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6604 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6605 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6606 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6607 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6608 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6609 R_BuildFogHeightTexture();
6610 // fog color was already set
6611 // update the fog texture
6612 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)
6613 R_BuildFogTexture();
6614 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6615 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6618 r_refdef.fogenabled = false;
6621 if (r_refdef.fog_density)
6623 r_refdef.fogcolor[0] = r_refdef.fog_red;
6624 r_refdef.fogcolor[1] = r_refdef.fog_green;
6625 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6627 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6628 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6629 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6630 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6634 VectorCopy(r_refdef.fogcolor, fogvec);
6635 // color.rgb *= ContrastBoost * SceneBrightness;
6636 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6637 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6638 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6639 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6644 void R_UpdateVariables(void)
6648 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6650 r_refdef.farclip = r_farclip_base.value;
6651 if (r_refdef.scene.worldmodel)
6652 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6653 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6655 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6656 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6657 r_refdef.polygonfactor = 0;
6658 r_refdef.polygonoffset = 0;
6659 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6660 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6662 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6663 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6664 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6665 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6666 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6667 if (FAKELIGHT_ENABLED)
6669 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6671 else if (r_refdef.scene.worldmodel)
6673 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
6675 if (r_showsurfaces.integer)
6677 r_refdef.scene.rtworld = false;
6678 r_refdef.scene.rtworldshadows = false;
6679 r_refdef.scene.rtdlight = false;
6680 r_refdef.scene.rtdlightshadows = false;
6681 r_refdef.lightmapintensity = 0;
6684 switch(vid.renderpath)
6686 case RENDERPATH_GL20:
6687 case RENDERPATH_D3D9:
6688 case RENDERPATH_D3D10:
6689 case RENDERPATH_D3D11:
6690 case RENDERPATH_SOFT:
6691 case RENDERPATH_GLES2:
6692 if(v_glslgamma.integer && !vid_gammatables_trivial)
6694 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6696 // build GLSL gamma texture
6697 #define RAMPWIDTH 256
6698 unsigned short ramp[RAMPWIDTH * 3];
6699 unsigned char rampbgr[RAMPWIDTH][4];
6702 r_texture_gammaramps_serial = vid_gammatables_serial;
6704 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6705 for(i = 0; i < RAMPWIDTH; ++i)
6707 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6708 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6709 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6712 if (r_texture_gammaramps)
6714 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6718 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6724 // remove GLSL gamma texture
6727 case RENDERPATH_GL11:
6728 case RENDERPATH_GL13:
6729 case RENDERPATH_GLES1:
6734 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6735 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6741 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6742 if( scenetype != r_currentscenetype ) {
6743 // store the old scenetype
6744 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6745 r_currentscenetype = scenetype;
6746 // move in the new scene
6747 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6756 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6758 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6759 if( scenetype == r_currentscenetype ) {
6760 return &r_refdef.scene;
6762 return &r_scenes_store[ scenetype ];
6766 static int R_SortEntities_Compare(const void *ap, const void *bp)
6768 const entity_render_t *a = *(const entity_render_t **)ap;
6769 const entity_render_t *b = *(const entity_render_t **)bp;
6772 if(a->model < b->model)
6774 if(a->model > b->model)
6778 // TODO possibly calculate the REAL skinnum here first using
6780 if(a->skinnum < b->skinnum)
6782 if(a->skinnum > b->skinnum)
6785 // everything we compared is equal
6788 static void R_SortEntities(void)
6790 // below or equal 2 ents, sorting never gains anything
6791 if(r_refdef.scene.numentities <= 2)
6794 qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6802 int dpsoftrast_test;
6803 extern cvar_t r_shadow_bouncegrid;
6804 void R_RenderView(void)
6806 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6808 rtexture_t *depthtexture;
6809 rtexture_t *colortexture;
6811 dpsoftrast_test = r_test.integer;
6813 if (r_timereport_active)
6814 R_TimeReport("start");
6815 r_textureframe++; // used only by R_GetCurrentTexture
6816 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6818 if(R_CompileShader_CheckStaticParms())
6821 if (!r_drawentities.integer)
6822 r_refdef.scene.numentities = 0;
6823 else if (r_sortentities.integer)
6826 R_AnimCache_ClearCache();
6827 R_FrameData_NewFrame();
6829 /* adjust for stereo display */
6830 if(R_Stereo_Active())
6832 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);
6833 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6836 if (r_refdef.view.isoverlay)
6838 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6839 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
6840 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6841 R_TimeReport("depthclear");
6843 r_refdef.view.showdebug = false;
6845 r_fb.water.enabled = false;
6846 r_fb.water.numwaterplanes = 0;
6848 R_RenderScene(0, NULL, NULL);
6850 r_refdef.view.matrix = originalmatrix;
6856 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6858 r_refdef.view.matrix = originalmatrix;
6862 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6864 if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
6865 // in sRGB fallback, behave similar to true sRGB: convert this
6866 // value from linear to sRGB
6867 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
6869 R_RenderView_UpdateViewVectors();
6871 R_Shadow_UpdateWorldLightSelection();
6873 R_Bloom_StartFrame();
6874 R_Water_StartFrame();
6876 // now we probably have an fbo to render into
6878 depthtexture = r_fb.depthtexture;
6879 colortexture = r_fb.colortexture;
6882 if (r_timereport_active)
6883 R_TimeReport("viewsetup");
6885 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6887 if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
6889 R_ClearScreen(r_refdef.fogenabled);
6890 if (r_timereport_active)
6891 R_TimeReport("viewclear");
6893 r_refdef.view.clear = true;
6895 r_refdef.view.showdebug = true;
6898 if (r_timereport_active)
6899 R_TimeReport("visibility");
6901 R_Shadow_UpdateBounceGridTexture();
6902 if (r_timereport_active && r_shadow_bouncegrid.integer)
6903 R_TimeReport("bouncegrid");
6905 r_fb.water.numwaterplanes = 0;
6906 if (r_fb.water.enabled)
6907 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
6909 R_RenderScene(fbo, depthtexture, colortexture);
6910 r_fb.water.numwaterplanes = 0;
6912 R_BlendView(fbo, depthtexture, colortexture);
6913 if (r_timereport_active)
6914 R_TimeReport("blendview");
6916 GL_Scissor(0, 0, vid.width, vid.height);
6917 GL_ScissorTest(false);
6919 r_refdef.view.matrix = originalmatrix;
6924 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6926 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6928 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6929 if (r_timereport_active)
6930 R_TimeReport("waterworld");
6933 // don't let sound skip if going slow
6934 if (r_refdef.scene.extraupdate)
6937 R_DrawModelsAddWaterPlanes();
6938 if (r_timereport_active)
6939 R_TimeReport("watermodels");
6941 if (r_fb.water.numwaterplanes)
6943 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
6944 if (r_timereport_active)
6945 R_TimeReport("waterscenes");
6949 extern cvar_t cl_locs_show;
6950 static void R_DrawLocs(void);
6951 static void R_DrawEntityBBoxes(void);
6952 static void R_DrawModelDecals(void);
6953 extern cvar_t cl_decals_newsystem;
6954 extern qboolean r_shadow_usingdeferredprepass;
6955 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6957 qboolean shadowmapping = false;
6959 if (r_timereport_active)
6960 R_TimeReport("beginscene");
6962 r_refdef.stats.renders++;
6966 // don't let sound skip if going slow
6967 if (r_refdef.scene.extraupdate)
6970 R_MeshQueue_BeginScene();
6974 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);
6976 if (r_timereport_active)
6977 R_TimeReport("skystartframe");
6979 if (cl.csqc_vidvars.drawworld)
6981 // don't let sound skip if going slow
6982 if (r_refdef.scene.extraupdate)
6985 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6987 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6988 if (r_timereport_active)
6989 R_TimeReport("worldsky");
6992 if (R_DrawBrushModelsSky() && r_timereport_active)
6993 R_TimeReport("bmodelsky");
6995 if (skyrendermasked && skyrenderlater)
6997 // we have to force off the water clipping plane while rendering sky
6998 R_SetupView(false, fbo, depthtexture, colortexture);
7000 R_SetupView(true, fbo, depthtexture, colortexture);
7001 if (r_timereport_active)
7002 R_TimeReport("sky");
7006 R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7007 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7008 R_Shadow_PrepareModelShadows();
7009 if (r_timereport_active)
7010 R_TimeReport("preparelights");
7012 if (R_Shadow_ShadowMappingEnabled())
7013 shadowmapping = true;
7015 if (r_shadow_usingdeferredprepass)
7016 R_Shadow_DrawPrepass();
7018 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7020 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7021 if (r_timereport_active)
7022 R_TimeReport("worlddepth");
7024 if (r_depthfirst.integer >= 2)
7026 R_DrawModelsDepth();
7027 if (r_timereport_active)
7028 R_TimeReport("modeldepth");
7031 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7033 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7034 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7035 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7036 // don't let sound skip if going slow
7037 if (r_refdef.scene.extraupdate)
7041 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7043 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7044 if (r_timereport_active)
7045 R_TimeReport("world");
7048 // don't let sound skip if going slow
7049 if (r_refdef.scene.extraupdate)
7053 if (r_timereport_active)
7054 R_TimeReport("models");
7056 // don't let sound skip if going slow
7057 if (r_refdef.scene.extraupdate)
7060 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7062 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7063 R_DrawModelShadows(fbo, depthtexture, colortexture);
7064 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7065 // don't let sound skip if going slow
7066 if (r_refdef.scene.extraupdate)
7070 if (!r_shadow_usingdeferredprepass)
7072 R_Shadow_DrawLights();
7073 if (r_timereport_active)
7074 R_TimeReport("rtlights");
7077 // don't let sound skip if going slow
7078 if (r_refdef.scene.extraupdate)
7081 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7083 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7084 R_DrawModelShadows(fbo, depthtexture, colortexture);
7085 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7086 // don't let sound skip if going slow
7087 if (r_refdef.scene.extraupdate)
7091 if (cl.csqc_vidvars.drawworld)
7093 if (cl_decals_newsystem.integer)
7095 R_DrawModelDecals();
7096 if (r_timereport_active)
7097 R_TimeReport("modeldecals");
7102 if (r_timereport_active)
7103 R_TimeReport("decals");
7107 if (r_timereport_active)
7108 R_TimeReport("particles");
7111 if (r_timereport_active)
7112 R_TimeReport("explosions");
7114 R_DrawLightningBeams();
7115 if (r_timereport_active)
7116 R_TimeReport("lightning");
7120 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7122 if (r_refdef.view.showdebug)
7124 if (cl_locs_show.integer)
7127 if (r_timereport_active)
7128 R_TimeReport("showlocs");
7131 if (r_drawportals.integer)
7134 if (r_timereport_active)
7135 R_TimeReport("portals");
7138 if (r_showbboxes.value > 0)
7140 R_DrawEntityBBoxes();
7141 if (r_timereport_active)
7142 R_TimeReport("bboxes");
7146 if (r_transparent.integer)
7148 R_MeshQueue_RenderTransparent();
7149 if (r_timereport_active)
7150 R_TimeReport("drawtrans");
7153 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))
7155 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7156 if (r_timereport_active)
7157 R_TimeReport("worlddebug");
7158 R_DrawModelsDebug();
7159 if (r_timereport_active)
7160 R_TimeReport("modeldebug");
7163 if (cl.csqc_vidvars.drawworld)
7165 R_Shadow_DrawCoronas();
7166 if (r_timereport_active)
7167 R_TimeReport("coronas");
7172 GL_DepthTest(false);
7173 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7174 GL_Color(1, 1, 1, 1);
7175 qglBegin(GL_POLYGON);
7176 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7177 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7178 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7179 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7181 qglBegin(GL_POLYGON);
7182 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]);
7183 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]);
7184 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]);
7185 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]);
7187 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7191 // don't let sound skip if going slow
7192 if (r_refdef.scene.extraupdate)
7196 static const unsigned short bboxelements[36] =
7206 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7209 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7211 RSurf_ActiveWorldEntity();
7213 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7214 GL_DepthMask(false);
7215 GL_DepthRange(0, 1);
7216 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7217 // R_Mesh_ResetTextureState();
7219 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7220 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7221 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7222 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7223 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7224 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7225 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7226 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7227 R_FillColors(color4f, 8, cr, cg, cb, ca);
7228 if (r_refdef.fogenabled)
7230 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7232 f1 = RSurf_FogVertex(v);
7234 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7235 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7236 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7239 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7240 R_Mesh_ResetTextureState();
7241 R_SetupShader_Generic_NoTexture(false, false);
7242 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7245 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7247 prvm_prog_t *prog = SVVM_prog;
7250 prvm_edict_t *edict;
7252 // this function draws bounding boxes of server entities
7256 GL_CullFace(GL_NONE);
7257 R_SetupShader_Generic_NoTexture(false, false);
7259 for (i = 0;i < numsurfaces;i++)
7261 edict = PRVM_EDICT_NUM(surfacelist[i]);
7262 switch ((int)PRVM_serveredictfloat(edict, solid))
7264 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7265 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7266 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7267 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7268 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7269 case SOLID_CORPSE: Vector4Set(color, 1, 0.5, 0, 0.05);break;
7270 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7272 color[3] *= r_showbboxes.value;
7273 color[3] = bound(0, color[3], 1);
7274 GL_DepthTest(!r_showdisabledepthtest.integer);
7275 GL_CullFace(r_refdef.view.cullface_front);
7276 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7280 static void R_DrawEntityBBoxes(void)
7283 prvm_edict_t *edict;
7285 prvm_prog_t *prog = SVVM_prog;
7287 // this function draws bounding boxes of server entities
7291 for (i = 0;i < prog->num_edicts;i++)
7293 edict = PRVM_EDICT_NUM(i);
7294 if (edict->priv.server->free)
7296 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7297 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7299 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7301 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7302 R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7306 static const int nomodelelement3i[24] =
7318 static const unsigned short nomodelelement3s[24] =
7330 static const float nomodelvertex3f[6*3] =
7340 static const float nomodelcolor4f[6*4] =
7342 0.0f, 0.0f, 0.5f, 1.0f,
7343 0.0f, 0.0f, 0.5f, 1.0f,
7344 0.0f, 0.5f, 0.0f, 1.0f,
7345 0.0f, 0.5f, 0.0f, 1.0f,
7346 0.5f, 0.0f, 0.0f, 1.0f,
7347 0.5f, 0.0f, 0.0f, 1.0f
7350 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7356 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);
7358 // this is only called once per entity so numsurfaces is always 1, and
7359 // surfacelist is always {0}, so this code does not handle batches
7361 if (rsurface.ent_flags & RENDER_ADDITIVE)
7363 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7364 GL_DepthMask(false);
7366 else if (rsurface.colormod[3] < 1)
7368 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7369 GL_DepthMask(false);
7373 GL_BlendFunc(GL_ONE, GL_ZERO);
7376 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7377 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7378 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7379 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7380 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7381 for (i = 0, c = color4f;i < 6;i++, c += 4)
7383 c[0] *= rsurface.colormod[0];
7384 c[1] *= rsurface.colormod[1];
7385 c[2] *= rsurface.colormod[2];
7386 c[3] *= rsurface.colormod[3];
7388 if (r_refdef.fogenabled)
7390 for (i = 0, c = color4f;i < 6;i++, c += 4)
7392 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7394 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7395 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7396 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7399 // R_Mesh_ResetTextureState();
7400 R_SetupShader_Generic_NoTexture(false, false);
7401 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7402 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7405 void R_DrawNoModel(entity_render_t *ent)
7408 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7409 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7410 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? MESHQUEUE_SORT_HUD : MESHQUEUE_SORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7412 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7415 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7417 vec3_t right1, right2, diff, normal;
7419 VectorSubtract (org2, org1, normal);
7421 // calculate 'right' vector for start
7422 VectorSubtract (r_refdef.view.origin, org1, diff);
7423 CrossProduct (normal, diff, right1);
7424 VectorNormalize (right1);
7426 // calculate 'right' vector for end
7427 VectorSubtract (r_refdef.view.origin, org2, diff);
7428 CrossProduct (normal, diff, right2);
7429 VectorNormalize (right2);
7431 vert[ 0] = org1[0] + width * right1[0];
7432 vert[ 1] = org1[1] + width * right1[1];
7433 vert[ 2] = org1[2] + width * right1[2];
7434 vert[ 3] = org1[0] - width * right1[0];
7435 vert[ 4] = org1[1] - width * right1[1];
7436 vert[ 5] = org1[2] - width * right1[2];
7437 vert[ 6] = org2[0] - width * right2[0];
7438 vert[ 7] = org2[1] - width * right2[1];
7439 vert[ 8] = org2[2] - width * right2[2];
7440 vert[ 9] = org2[0] + width * right2[0];
7441 vert[10] = org2[1] + width * right2[1];
7442 vert[11] = org2[2] + width * right2[2];
7445 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)
7447 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7448 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7449 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7450 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7451 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7452 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7453 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7454 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7455 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7456 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7457 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7458 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7461 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7466 VectorSet(v, x, y, z);
7467 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7468 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7470 if (i == mesh->numvertices)
7472 if (mesh->numvertices < mesh->maxvertices)
7474 VectorCopy(v, vertex3f);
7475 mesh->numvertices++;
7477 return mesh->numvertices;
7483 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7487 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7488 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7489 e = mesh->element3i + mesh->numtriangles * 3;
7490 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7492 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7493 if (mesh->numtriangles < mesh->maxtriangles)
7498 mesh->numtriangles++;
7500 element[1] = element[2];
7504 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7508 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7509 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7510 e = mesh->element3i + mesh->numtriangles * 3;
7511 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7513 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7514 if (mesh->numtriangles < mesh->maxtriangles)
7519 mesh->numtriangles++;
7521 element[1] = element[2];
7525 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7526 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7528 int planenum, planenum2;
7531 mplane_t *plane, *plane2;
7533 double temppoints[2][256*3];
7534 // figure out how large a bounding box we need to properly compute this brush
7536 for (w = 0;w < numplanes;w++)
7537 maxdist = max(maxdist, fabs(planes[w].dist));
7538 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7539 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7540 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7544 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7545 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7547 if (planenum2 == planenum)
7549 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);
7552 if (tempnumpoints < 3)
7554 // generate elements forming a triangle fan for this polygon
7555 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7559 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)
7561 texturelayer_t *layer;
7562 layer = t->currentlayers + t->currentnumlayers++;
7564 layer->depthmask = depthmask;
7565 layer->blendfunc1 = blendfunc1;
7566 layer->blendfunc2 = blendfunc2;
7567 layer->texture = texture;
7568 layer->texmatrix = *matrix;
7569 layer->color[0] = r;
7570 layer->color[1] = g;
7571 layer->color[2] = b;
7572 layer->color[3] = a;
7575 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7577 if(parms[0] == 0 && parms[1] == 0)
7579 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7580 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7585 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7588 index = parms[2] + rsurface.shadertime * parms[3];
7589 index -= floor(index);
7590 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7593 case Q3WAVEFUNC_NONE:
7594 case Q3WAVEFUNC_NOISE:
7595 case Q3WAVEFUNC_COUNT:
7598 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7599 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7600 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7601 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7602 case Q3WAVEFUNC_TRIANGLE:
7604 f = index - floor(index);
7617 f = parms[0] + parms[1] * f;
7618 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7619 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7623 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7629 matrix4x4_t matrix, temp;
7630 switch(tcmod->tcmod)
7634 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7635 matrix = r_waterscrollmatrix;
7637 matrix = identitymatrix;
7639 case Q3TCMOD_ENTITYTRANSLATE:
7640 // this is used in Q3 to allow the gamecode to control texcoord
7641 // scrolling on the entity, which is not supported in darkplaces yet.
7642 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7644 case Q3TCMOD_ROTATE:
7645 f = tcmod->parms[0] * rsurface.shadertime;
7646 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7647 Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
7648 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7651 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7653 case Q3TCMOD_SCROLL:
7654 // extra care is needed because of precision breakdown with large values of time
7655 offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7656 offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7657 Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7659 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7660 w = (int) tcmod->parms[0];
7661 h = (int) tcmod->parms[1];
7662 f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7664 idx = (int) floor(f * w * h);
7665 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7667 case Q3TCMOD_STRETCH:
7668 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7669 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7671 case Q3TCMOD_TRANSFORM:
7672 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7673 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7674 VectorSet(tcmat + 6, 0 , 0 , 1);
7675 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7676 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7678 case Q3TCMOD_TURBULENT:
7679 // this is handled in the RSurf_PrepareVertices function
7680 matrix = identitymatrix;
7684 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7687 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7689 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7690 char name[MAX_QPATH];
7691 skinframe_t *skinframe;
7692 unsigned char pixels[296*194];
7693 strlcpy(cache->name, skinname, sizeof(cache->name));
7694 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7695 if (developer_loading.integer)
7696 Con_Printf("loading %s\n", name);
7697 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7698 if (!skinframe || !skinframe->base)
7701 fs_offset_t filesize;
7703 f = FS_LoadFile(name, tempmempool, true, &filesize);
7706 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7707 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7711 cache->skinframe = skinframe;
7714 texture_t *R_GetCurrentTexture(texture_t *t)
7717 const entity_render_t *ent = rsurface.entity;
7718 dp_model_t *model = ent->model;
7719 q3shaderinfo_layer_tcmod_t *tcmod;
7721 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7722 return t->currentframe;
7723 t->update_lastrenderframe = r_textureframe;
7724 t->update_lastrenderentity = (void *)ent;
7726 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7727 t->camera_entity = ent->entitynumber;
7729 t->camera_entity = 0;
7731 // switch to an alternate material if this is a q1bsp animated material
7733 texture_t *texture = t;
7734 int s = rsurface.ent_skinnum;
7735 if ((unsigned int)s >= (unsigned int)model->numskins)
7737 if (model->skinscenes)
7739 if (model->skinscenes[s].framecount > 1)
7740 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7742 s = model->skinscenes[s].firstframe;
7745 t = t + s * model->num_surfaces;
7748 // use an alternate animation if the entity's frame is not 0,
7749 // and only if the texture has an alternate animation
7750 if (rsurface.ent_alttextures && t->anim_total[1])
7751 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7753 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7755 texture->currentframe = t;
7758 // update currentskinframe to be a qw skin or animation frame
7759 if (rsurface.ent_qwskin >= 0)
7761 i = rsurface.ent_qwskin;
7762 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7764 r_qwskincache_size = cl.maxclients;
7766 Mem_Free(r_qwskincache);
7767 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7769 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7770 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7771 t->currentskinframe = r_qwskincache[i].skinframe;
7772 if (t->currentskinframe == NULL)
7773 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7775 else if (t->numskinframes >= 2)
7776 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7777 if (t->backgroundnumskinframes >= 2)
7778 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7780 t->currentmaterialflags = t->basematerialflags;
7781 t->currentalpha = rsurface.colormod[3];
7782 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7783 t->currentalpha *= r_wateralpha.value;
7784 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
7785 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7786 if(!r_fb.water.enabled || r_refdef.view.isoverlay)
7787 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7788 if (!(rsurface.ent_flags & RENDER_LIGHT))
7789 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7790 else if (FAKELIGHT_ENABLED)
7792 // no modellight if using fakelight for the map
7794 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7796 // pick a model lighting mode
7797 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7798 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7800 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7802 if (rsurface.ent_flags & RENDER_ADDITIVE)
7803 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7804 else if (t->currentalpha < 1)
7805 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7806 // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
7807 if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7808 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
7809 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7810 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7811 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7812 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7813 if (t->backgroundnumskinframes)
7814 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7815 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7817 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7818 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7821 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7822 if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7824 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7825 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7827 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7828 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7830 // there is no tcmod
7831 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7833 t->currenttexmatrix = r_waterscrollmatrix;
7834 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7836 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7838 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7839 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7842 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7843 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7844 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7845 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7847 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7848 if (t->currentskinframe->qpixels)
7849 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7850 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7851 if (!t->basetexture)
7852 t->basetexture = r_texture_notexture;
7853 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7854 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7855 t->nmaptexture = t->currentskinframe->nmap;
7856 if (!t->nmaptexture)
7857 t->nmaptexture = r_texture_blanknormalmap;
7858 t->glosstexture = r_texture_black;
7859 t->glowtexture = t->currentskinframe->glow;
7860 t->fogtexture = t->currentskinframe->fog;
7861 t->reflectmasktexture = t->currentskinframe->reflect;
7862 if (t->backgroundnumskinframes)
7864 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7865 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7866 t->backgroundglosstexture = r_texture_black;
7867 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7868 if (!t->backgroundnmaptexture)
7869 t->backgroundnmaptexture = r_texture_blanknormalmap;
7873 t->backgroundbasetexture = r_texture_white;
7874 t->backgroundnmaptexture = r_texture_blanknormalmap;
7875 t->backgroundglosstexture = r_texture_black;
7876 t->backgroundglowtexture = NULL;
7878 t->specularpower = r_shadow_glossexponent.value;
7879 // TODO: store reference values for these in the texture?
7880 t->specularscale = 0;
7881 if (r_shadow_gloss.integer > 0)
7883 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7885 if (r_shadow_glossintensity.value > 0)
7887 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7888 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7889 t->specularscale = r_shadow_glossintensity.value;
7892 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7894 t->glosstexture = r_texture_white;
7895 t->backgroundglosstexture = r_texture_white;
7896 t->specularscale = r_shadow_gloss2intensity.value;
7897 t->specularpower = r_shadow_gloss2exponent.value;
7900 t->specularscale *= t->specularscalemod;
7901 t->specularpower *= t->specularpowermod;
7902 t->rtlightambient = 0;
7904 // lightmaps mode looks bad with dlights using actual texturing, so turn
7905 // off the colormap and glossmap, but leave the normalmap on as it still
7906 // accurately represents the shading involved
7907 if (gl_lightmaps.integer)
7909 t->basetexture = r_texture_grey128;
7910 t->pantstexture = r_texture_black;
7911 t->shirttexture = r_texture_black;
7912 t->nmaptexture = r_texture_blanknormalmap;
7913 t->glosstexture = r_texture_black;
7914 t->glowtexture = NULL;
7915 t->fogtexture = NULL;
7916 t->reflectmasktexture = NULL;
7917 t->backgroundbasetexture = NULL;
7918 t->backgroundnmaptexture = r_texture_blanknormalmap;
7919 t->backgroundglosstexture = r_texture_black;
7920 t->backgroundglowtexture = NULL;
7921 t->specularscale = 0;
7922 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7925 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7926 VectorClear(t->dlightcolor);
7927 t->currentnumlayers = 0;
7928 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7930 int blendfunc1, blendfunc2;
7932 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7934 blendfunc1 = GL_SRC_ALPHA;
7935 blendfunc2 = GL_ONE;
7937 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7939 blendfunc1 = GL_SRC_ALPHA;
7940 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7942 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7944 blendfunc1 = t->customblendfunc[0];
7945 blendfunc2 = t->customblendfunc[1];
7949 blendfunc1 = GL_ONE;
7950 blendfunc2 = GL_ZERO;
7952 // don't colormod evilblend textures
7953 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7954 VectorSet(t->lightmapcolor, 1, 1, 1);
7955 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7956 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7958 // fullbright is not affected by r_refdef.lightmapintensity
7959 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]);
7960 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7961 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]);
7962 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7963 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]);
7967 vec3_t ambientcolor;
7969 // set the color tint used for lights affecting this surface
7970 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7972 // q3bsp has no lightmap updates, so the lightstylevalue that
7973 // would normally be baked into the lightmap must be
7974 // applied to the color
7975 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7976 if (model->type == mod_brushq3)
7977 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7978 colorscale *= r_refdef.lightmapintensity;
7979 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7980 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7981 // basic lit geometry
7982 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]);
7983 // add pants/shirt if needed
7984 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7985 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]);
7986 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7987 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]);
7988 // now add ambient passes if needed
7989 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7991 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]);
7992 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7993 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]);
7994 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7995 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]);
7998 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7999 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]);
8000 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8002 // if this is opaque use alpha blend which will darken the earlier
8005 // if this is an alpha blended material, all the earlier passes
8006 // were darkened by fog already, so we only need to add the fog
8007 // color ontop through the fog mask texture
8009 // if this is an additive blended material, all the earlier passes
8010 // were darkened by fog already, and we should not add fog color
8011 // (because the background was not darkened, there is no fog color
8012 // that was lost behind it).
8013 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]);
8017 return t->currentframe;
8020 rsurfacestate_t rsurface;
8022 void RSurf_ActiveWorldEntity(void)
8024 dp_model_t *model = r_refdef.scene.worldmodel;
8025 //if (rsurface.entity == r_refdef.scene.worldentity)
8027 rsurface.entity = r_refdef.scene.worldentity;
8028 rsurface.skeleton = NULL;
8029 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8030 rsurface.ent_skinnum = 0;
8031 rsurface.ent_qwskin = -1;
8032 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8033 rsurface.shadertime = r_refdef.scene.time;
8034 rsurface.matrix = identitymatrix;
8035 rsurface.inversematrix = identitymatrix;
8036 rsurface.matrixscale = 1;
8037 rsurface.inversematrixscale = 1;
8038 R_EntityMatrix(&identitymatrix);
8039 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8040 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8041 rsurface.fograngerecip = r_refdef.fograngerecip;
8042 rsurface.fogheightfade = r_refdef.fogheightfade;
8043 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8044 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8045 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8046 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8047 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8048 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8049 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8050 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8051 rsurface.colormod[3] = 1;
8052 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);
8053 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8054 rsurface.frameblend[0].lerp = 1;
8055 rsurface.ent_alttextures = false;
8056 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8057 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8058 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8059 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8060 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8061 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8062 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8063 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8064 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8065 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8066 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8067 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8068 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8069 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8070 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8071 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8072 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8073 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8074 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8075 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8076 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8077 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8078 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8079 rsurface.modelelement3i = model->surfmesh.data_element3i;
8080 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8081 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8082 rsurface.modelelement3s = model->surfmesh.data_element3s;
8083 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8084 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8085 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8086 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8087 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8088 rsurface.modelsurfaces = model->data_surfaces;
8089 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8090 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8091 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8092 rsurface.modelgeneratedvertex = false;
8093 rsurface.batchgeneratedvertex = false;
8094 rsurface.batchfirstvertex = 0;
8095 rsurface.batchnumvertices = 0;
8096 rsurface.batchfirsttriangle = 0;
8097 rsurface.batchnumtriangles = 0;
8098 rsurface.batchvertex3f = NULL;
8099 rsurface.batchvertex3f_vertexbuffer = NULL;
8100 rsurface.batchvertex3f_bufferoffset = 0;
8101 rsurface.batchsvector3f = NULL;
8102 rsurface.batchsvector3f_vertexbuffer = NULL;
8103 rsurface.batchsvector3f_bufferoffset = 0;
8104 rsurface.batchtvector3f = NULL;
8105 rsurface.batchtvector3f_vertexbuffer = NULL;
8106 rsurface.batchtvector3f_bufferoffset = 0;
8107 rsurface.batchnormal3f = NULL;
8108 rsurface.batchnormal3f_vertexbuffer = NULL;
8109 rsurface.batchnormal3f_bufferoffset = 0;
8110 rsurface.batchlightmapcolor4f = NULL;
8111 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8112 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8113 rsurface.batchtexcoordtexture2f = NULL;
8114 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8115 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8116 rsurface.batchtexcoordlightmap2f = NULL;
8117 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8118 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8119 rsurface.batchvertexmesh = NULL;
8120 rsurface.batchvertexmeshbuffer = NULL;
8121 rsurface.batchvertex3fbuffer = NULL;
8122 rsurface.batchelement3i = NULL;
8123 rsurface.batchelement3i_indexbuffer = NULL;
8124 rsurface.batchelement3i_bufferoffset = 0;
8125 rsurface.batchelement3s = NULL;
8126 rsurface.batchelement3s_indexbuffer = NULL;
8127 rsurface.batchelement3s_bufferoffset = 0;
8128 rsurface.passcolor4f = NULL;
8129 rsurface.passcolor4f_vertexbuffer = NULL;
8130 rsurface.passcolor4f_bufferoffset = 0;
8133 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8135 dp_model_t *model = ent->model;
8136 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8138 rsurface.entity = (entity_render_t *)ent;
8139 rsurface.skeleton = ent->skeleton;
8140 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8141 rsurface.ent_skinnum = ent->skinnum;
8142 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;
8143 rsurface.ent_flags = ent->flags;
8144 rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8145 rsurface.matrix = ent->matrix;
8146 rsurface.inversematrix = ent->inversematrix;
8147 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8148 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8149 R_EntityMatrix(&rsurface.matrix);
8150 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8151 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8152 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8153 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8154 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8155 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8156 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8157 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8158 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8159 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8160 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8161 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8162 rsurface.colormod[3] = ent->alpha;
8163 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8164 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8165 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8166 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8167 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8168 if (ent->model->brush.submodel && !prepass)
8170 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8171 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8173 if (model->surfmesh.isanimated && model->AnimateVertices)
8175 if (ent->animcache_vertex3f)
8177 rsurface.modelvertex3f = ent->animcache_vertex3f;
8178 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8179 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8180 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8181 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8182 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8183 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8185 else if (wanttangents)
8187 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8188 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8189 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8190 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8191 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8192 rsurface.modelvertexmesh = NULL;
8193 rsurface.modelvertexmeshbuffer = NULL;
8194 rsurface.modelvertex3fbuffer = NULL;
8196 else if (wantnormals)
8198 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8199 rsurface.modelsvector3f = NULL;
8200 rsurface.modeltvector3f = NULL;
8201 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8202 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8203 rsurface.modelvertexmesh = NULL;
8204 rsurface.modelvertexmeshbuffer = NULL;
8205 rsurface.modelvertex3fbuffer = NULL;
8209 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8210 rsurface.modelsvector3f = NULL;
8211 rsurface.modeltvector3f = NULL;
8212 rsurface.modelnormal3f = NULL;
8213 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8214 rsurface.modelvertexmesh = NULL;
8215 rsurface.modelvertexmeshbuffer = NULL;
8216 rsurface.modelvertex3fbuffer = NULL;
8218 rsurface.modelvertex3f_vertexbuffer = 0;
8219 rsurface.modelvertex3f_bufferoffset = 0;
8220 rsurface.modelsvector3f_vertexbuffer = 0;
8221 rsurface.modelsvector3f_bufferoffset = 0;
8222 rsurface.modeltvector3f_vertexbuffer = 0;
8223 rsurface.modeltvector3f_bufferoffset = 0;
8224 rsurface.modelnormal3f_vertexbuffer = 0;
8225 rsurface.modelnormal3f_bufferoffset = 0;
8226 rsurface.modelgeneratedvertex = true;
8230 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8231 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8232 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8233 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8234 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8235 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8236 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8237 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8238 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8239 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8240 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8241 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8242 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8243 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8244 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8245 rsurface.modelgeneratedvertex = false;
8247 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8248 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8249 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8250 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8251 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8252 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8253 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8254 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8255 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8256 rsurface.modelelement3i = model->surfmesh.data_element3i;
8257 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8258 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8259 rsurface.modelelement3s = model->surfmesh.data_element3s;
8260 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8261 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8262 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8263 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8264 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8265 rsurface.modelsurfaces = model->data_surfaces;
8266 rsurface.batchgeneratedvertex = false;
8267 rsurface.batchfirstvertex = 0;
8268 rsurface.batchnumvertices = 0;
8269 rsurface.batchfirsttriangle = 0;
8270 rsurface.batchnumtriangles = 0;
8271 rsurface.batchvertex3f = NULL;
8272 rsurface.batchvertex3f_vertexbuffer = NULL;
8273 rsurface.batchvertex3f_bufferoffset = 0;
8274 rsurface.batchsvector3f = NULL;
8275 rsurface.batchsvector3f_vertexbuffer = NULL;
8276 rsurface.batchsvector3f_bufferoffset = 0;
8277 rsurface.batchtvector3f = NULL;
8278 rsurface.batchtvector3f_vertexbuffer = NULL;
8279 rsurface.batchtvector3f_bufferoffset = 0;
8280 rsurface.batchnormal3f = NULL;
8281 rsurface.batchnormal3f_vertexbuffer = NULL;
8282 rsurface.batchnormal3f_bufferoffset = 0;
8283 rsurface.batchlightmapcolor4f = NULL;
8284 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8285 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8286 rsurface.batchtexcoordtexture2f = NULL;
8287 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8288 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8289 rsurface.batchtexcoordlightmap2f = NULL;
8290 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8291 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8292 rsurface.batchvertexmesh = NULL;
8293 rsurface.batchvertexmeshbuffer = NULL;
8294 rsurface.batchvertex3fbuffer = NULL;
8295 rsurface.batchelement3i = NULL;
8296 rsurface.batchelement3i_indexbuffer = NULL;
8297 rsurface.batchelement3i_bufferoffset = 0;
8298 rsurface.batchelement3s = NULL;
8299 rsurface.batchelement3s_indexbuffer = NULL;
8300 rsurface.batchelement3s_bufferoffset = 0;
8301 rsurface.passcolor4f = NULL;
8302 rsurface.passcolor4f_vertexbuffer = NULL;
8303 rsurface.passcolor4f_bufferoffset = 0;
8306 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)
8308 rsurface.entity = r_refdef.scene.worldentity;
8309 rsurface.skeleton = NULL;
8310 rsurface.ent_skinnum = 0;
8311 rsurface.ent_qwskin = -1;
8312 rsurface.ent_flags = entflags;
8313 rsurface.shadertime = r_refdef.scene.time - shadertime;
8314 rsurface.modelnumvertices = numvertices;
8315 rsurface.modelnumtriangles = numtriangles;
8316 rsurface.matrix = *matrix;
8317 rsurface.inversematrix = *inversematrix;
8318 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8319 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8320 R_EntityMatrix(&rsurface.matrix);
8321 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8322 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8323 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8324 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8325 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8326 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8327 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8328 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8329 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8330 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8331 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8332 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8333 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);
8334 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8335 rsurface.frameblend[0].lerp = 1;
8336 rsurface.ent_alttextures = false;
8337 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8338 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8341 rsurface.modelvertex3f = (float *)vertex3f;
8342 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8343 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8344 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8346 else if (wantnormals)
8348 rsurface.modelvertex3f = (float *)vertex3f;
8349 rsurface.modelsvector3f = NULL;
8350 rsurface.modeltvector3f = NULL;
8351 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8355 rsurface.modelvertex3f = (float *)vertex3f;
8356 rsurface.modelsvector3f = NULL;
8357 rsurface.modeltvector3f = NULL;
8358 rsurface.modelnormal3f = NULL;
8360 rsurface.modelvertexmesh = NULL;
8361 rsurface.modelvertexmeshbuffer = NULL;
8362 rsurface.modelvertex3fbuffer = NULL;
8363 rsurface.modelvertex3f_vertexbuffer = 0;
8364 rsurface.modelvertex3f_bufferoffset = 0;
8365 rsurface.modelsvector3f_vertexbuffer = 0;
8366 rsurface.modelsvector3f_bufferoffset = 0;
8367 rsurface.modeltvector3f_vertexbuffer = 0;
8368 rsurface.modeltvector3f_bufferoffset = 0;
8369 rsurface.modelnormal3f_vertexbuffer = 0;
8370 rsurface.modelnormal3f_bufferoffset = 0;
8371 rsurface.modelgeneratedvertex = true;
8372 rsurface.modellightmapcolor4f = (float *)color4f;
8373 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8374 rsurface.modellightmapcolor4f_bufferoffset = 0;
8375 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8376 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8377 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8378 rsurface.modeltexcoordlightmap2f = NULL;
8379 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8380 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8381 rsurface.modelelement3i = (int *)element3i;
8382 rsurface.modelelement3i_indexbuffer = NULL;
8383 rsurface.modelelement3i_bufferoffset = 0;
8384 rsurface.modelelement3s = (unsigned short *)element3s;
8385 rsurface.modelelement3s_indexbuffer = NULL;
8386 rsurface.modelelement3s_bufferoffset = 0;
8387 rsurface.modellightmapoffsets = NULL;
8388 rsurface.modelsurfaces = NULL;
8389 rsurface.batchgeneratedvertex = false;
8390 rsurface.batchfirstvertex = 0;
8391 rsurface.batchnumvertices = 0;
8392 rsurface.batchfirsttriangle = 0;
8393 rsurface.batchnumtriangles = 0;
8394 rsurface.batchvertex3f = NULL;
8395 rsurface.batchvertex3f_vertexbuffer = NULL;
8396 rsurface.batchvertex3f_bufferoffset = 0;
8397 rsurface.batchsvector3f = NULL;
8398 rsurface.batchsvector3f_vertexbuffer = NULL;
8399 rsurface.batchsvector3f_bufferoffset = 0;
8400 rsurface.batchtvector3f = NULL;
8401 rsurface.batchtvector3f_vertexbuffer = NULL;
8402 rsurface.batchtvector3f_bufferoffset = 0;
8403 rsurface.batchnormal3f = NULL;
8404 rsurface.batchnormal3f_vertexbuffer = NULL;
8405 rsurface.batchnormal3f_bufferoffset = 0;
8406 rsurface.batchlightmapcolor4f = NULL;
8407 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8408 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8409 rsurface.batchtexcoordtexture2f = NULL;
8410 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8411 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8412 rsurface.batchtexcoordlightmap2f = NULL;
8413 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8414 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8415 rsurface.batchvertexmesh = NULL;
8416 rsurface.batchvertexmeshbuffer = NULL;
8417 rsurface.batchvertex3fbuffer = NULL;
8418 rsurface.batchelement3i = NULL;
8419 rsurface.batchelement3i_indexbuffer = NULL;
8420 rsurface.batchelement3i_bufferoffset = 0;
8421 rsurface.batchelement3s = NULL;
8422 rsurface.batchelement3s_indexbuffer = NULL;
8423 rsurface.batchelement3s_bufferoffset = 0;
8424 rsurface.passcolor4f = NULL;
8425 rsurface.passcolor4f_vertexbuffer = NULL;
8426 rsurface.passcolor4f_bufferoffset = 0;
8428 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8430 if ((wantnormals || wanttangents) && !normal3f)
8432 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8433 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8435 if (wanttangents && !svector3f)
8437 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8438 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8439 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8444 float RSurf_FogPoint(const float *v)
8446 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8447 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8448 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8449 float FogHeightFade = r_refdef.fogheightfade;
8451 unsigned int fogmasktableindex;
8452 if (r_refdef.fogplaneviewabove)
8453 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8455 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8456 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8457 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8460 float RSurf_FogVertex(const float *v)
8462 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8463 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8464 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8465 float FogHeightFade = rsurface.fogheightfade;
8467 unsigned int fogmasktableindex;
8468 if (r_refdef.fogplaneviewabove)
8469 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8471 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8472 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8473 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8476 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8479 for (i = 0;i < numelements;i++)
8480 outelement3i[i] = inelement3i[i] + adjust;
8483 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8484 extern cvar_t gl_vbo;
8485 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8493 int surfacefirsttriangle;
8494 int surfacenumtriangles;
8495 int surfacefirstvertex;
8496 int surfaceendvertex;
8497 int surfacenumvertices;
8498 int batchnumvertices;
8499 int batchnumtriangles;
8503 qboolean dynamicvertex;
8507 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8509 q3shaderinfo_deform_t *deform;
8510 const msurface_t *surface, *firstsurface;
8511 r_vertexmesh_t *vertexmesh;
8512 if (!texturenumsurfaces)
8514 // find vertex range of this surface batch
8516 firstsurface = texturesurfacelist[0];
8517 firsttriangle = firstsurface->num_firsttriangle;
8518 batchnumvertices = 0;
8519 batchnumtriangles = 0;
8520 firstvertex = endvertex = firstsurface->num_firstvertex;
8521 for (i = 0;i < texturenumsurfaces;i++)
8523 surface = texturesurfacelist[i];
8524 if (surface != firstsurface + i)
8526 surfacefirstvertex = surface->num_firstvertex;
8527 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8528 surfacenumvertices = surface->num_vertices;
8529 surfacenumtriangles = surface->num_triangles;
8530 if (firstvertex > surfacefirstvertex)
8531 firstvertex = surfacefirstvertex;
8532 if (endvertex < surfaceendvertex)
8533 endvertex = surfaceendvertex;
8534 batchnumvertices += surfacenumvertices;
8535 batchnumtriangles += surfacenumtriangles;
8538 // we now know the vertex range used, and if there are any gaps in it
8539 rsurface.batchfirstvertex = firstvertex;
8540 rsurface.batchnumvertices = endvertex - firstvertex;
8541 rsurface.batchfirsttriangle = firsttriangle;
8542 rsurface.batchnumtriangles = batchnumtriangles;
8544 // this variable holds flags for which properties have been updated that
8545 // may require regenerating vertexmesh array...
8548 // check if any dynamic vertex processing must occur
8549 dynamicvertex = false;
8551 // if there is a chance of animated vertex colors, it's a dynamic batch
8552 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8554 dynamicvertex = true;
8555 batchneed |= BATCHNEED_NOGAPS;
8556 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8559 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8561 switch (deform->deform)
8564 case Q3DEFORM_PROJECTIONSHADOW:
8565 case Q3DEFORM_TEXT0:
8566 case Q3DEFORM_TEXT1:
8567 case Q3DEFORM_TEXT2:
8568 case Q3DEFORM_TEXT3:
8569 case Q3DEFORM_TEXT4:
8570 case Q3DEFORM_TEXT5:
8571 case Q3DEFORM_TEXT6:
8572 case Q3DEFORM_TEXT7:
8575 case Q3DEFORM_AUTOSPRITE:
8576 dynamicvertex = true;
8577 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8578 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8580 case Q3DEFORM_AUTOSPRITE2:
8581 dynamicvertex = true;
8582 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8583 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8585 case Q3DEFORM_NORMAL:
8586 dynamicvertex = true;
8587 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8588 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8591 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8592 break; // if wavefunc is a nop, ignore this transform
8593 dynamicvertex = true;
8594 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8595 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8597 case Q3DEFORM_BULGE:
8598 dynamicvertex = true;
8599 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8600 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8603 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8604 break; // if wavefunc is a nop, ignore this transform
8605 dynamicvertex = true;
8606 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8607 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8611 switch(rsurface.texture->tcgen.tcgen)
8614 case Q3TCGEN_TEXTURE:
8616 case Q3TCGEN_LIGHTMAP:
8617 dynamicvertex = true;
8618 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8619 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8621 case Q3TCGEN_VECTOR:
8622 dynamicvertex = true;
8623 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8624 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8626 case Q3TCGEN_ENVIRONMENT:
8627 dynamicvertex = true;
8628 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8629 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8632 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8634 dynamicvertex = true;
8635 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8636 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8639 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8641 dynamicvertex = true;
8642 batchneed |= BATCHNEED_NOGAPS;
8643 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8646 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8648 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8649 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8650 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8651 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8652 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8653 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8654 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8657 // when the model data has no vertex buffer (dynamic mesh), we need to
8659 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8660 batchneed |= BATCHNEED_NOGAPS;
8662 // if needsupdate, we have to do a dynamic vertex batch for sure
8663 if (needsupdate & batchneed)
8664 dynamicvertex = true;
8666 // see if we need to build vertexmesh from arrays
8667 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8668 dynamicvertex = true;
8670 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8671 // also some drivers strongly dislike firstvertex
8672 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8673 dynamicvertex = true;
8675 rsurface.batchvertex3f = rsurface.modelvertex3f;
8676 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8677 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8678 rsurface.batchsvector3f = rsurface.modelsvector3f;
8679 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8680 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8681 rsurface.batchtvector3f = rsurface.modeltvector3f;
8682 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8683 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8684 rsurface.batchnormal3f = rsurface.modelnormal3f;
8685 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8686 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8687 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8688 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8689 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8690 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8691 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8692 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8693 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8694 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8695 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8696 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8697 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8698 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8699 rsurface.batchelement3i = rsurface.modelelement3i;
8700 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8701 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8702 rsurface.batchelement3s = rsurface.modelelement3s;
8703 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8704 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8706 // if any dynamic vertex processing has to occur in software, we copy the
8707 // entire surface list together before processing to rebase the vertices
8708 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8710 // if any gaps exist and we do not have a static vertex buffer, we have to
8711 // copy the surface list together to avoid wasting upload bandwidth on the
8712 // vertices in the gaps.
8714 // if gaps exist and we have a static vertex buffer, we still have to
8715 // combine the index buffer ranges into one dynamic index buffer.
8717 // in all cases we end up with data that can be drawn in one call.
8721 // static vertex data, just set pointers...
8722 rsurface.batchgeneratedvertex = false;
8723 // if there are gaps, we want to build a combined index buffer,
8724 // otherwise use the original static buffer with an appropriate offset
8727 // build a new triangle elements array for this batch
8728 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8729 rsurface.batchfirsttriangle = 0;
8731 for (i = 0;i < texturenumsurfaces;i++)
8733 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8734 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8735 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8736 numtriangles += surfacenumtriangles;
8738 rsurface.batchelement3i_indexbuffer = NULL;
8739 rsurface.batchelement3i_bufferoffset = 0;
8740 rsurface.batchelement3s = NULL;
8741 rsurface.batchelement3s_indexbuffer = NULL;
8742 rsurface.batchelement3s_bufferoffset = 0;
8743 if (endvertex <= 65536)
8745 // make a 16bit (unsigned short) index array if possible
8746 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8747 for (i = 0;i < numtriangles*3;i++)
8748 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8754 // something needs software processing, do it for real...
8755 // we only directly handle separate array data in this case and then
8756 // generate interleaved data if needed...
8757 rsurface.batchgeneratedvertex = true;
8759 // now copy the vertex data into a combined array and make an index array
8760 // (this is what Quake3 does all the time)
8761 //if (gaps || rsurface.batchfirstvertex)
8763 rsurface.batchvertex3fbuffer = NULL;
8764 rsurface.batchvertexmesh = NULL;
8765 rsurface.batchvertexmeshbuffer = NULL;
8766 rsurface.batchvertex3f = NULL;
8767 rsurface.batchvertex3f_vertexbuffer = NULL;
8768 rsurface.batchvertex3f_bufferoffset = 0;
8769 rsurface.batchsvector3f = NULL;
8770 rsurface.batchsvector3f_vertexbuffer = NULL;
8771 rsurface.batchsvector3f_bufferoffset = 0;
8772 rsurface.batchtvector3f = NULL;
8773 rsurface.batchtvector3f_vertexbuffer = NULL;
8774 rsurface.batchtvector3f_bufferoffset = 0;
8775 rsurface.batchnormal3f = NULL;
8776 rsurface.batchnormal3f_vertexbuffer = NULL;
8777 rsurface.batchnormal3f_bufferoffset = 0;
8778 rsurface.batchlightmapcolor4f = NULL;
8779 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8780 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8781 rsurface.batchtexcoordtexture2f = NULL;
8782 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8783 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8784 rsurface.batchtexcoordlightmap2f = NULL;
8785 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8786 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8787 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8788 rsurface.batchelement3i_indexbuffer = NULL;
8789 rsurface.batchelement3i_bufferoffset = 0;
8790 rsurface.batchelement3s = NULL;
8791 rsurface.batchelement3s_indexbuffer = NULL;
8792 rsurface.batchelement3s_bufferoffset = 0;
8793 // we'll only be setting up certain arrays as needed
8794 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8795 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8796 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8797 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8798 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8799 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8800 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8802 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8803 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8805 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8806 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8807 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8808 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8809 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8810 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8813 for (i = 0;i < texturenumsurfaces;i++)
8815 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8816 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8817 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8818 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8819 // copy only the data requested
8820 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8821 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8822 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8824 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8826 if (rsurface.batchvertex3f)
8827 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8829 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8831 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8833 if (rsurface.modelnormal3f)
8834 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8836 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8838 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8840 if (rsurface.modelsvector3f)
8842 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8843 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8847 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8848 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8851 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8853 if (rsurface.modellightmapcolor4f)
8854 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8856 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8858 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8860 if (rsurface.modeltexcoordtexture2f)
8861 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8863 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8865 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8867 if (rsurface.modeltexcoordlightmap2f)
8868 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8870 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8873 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8874 numvertices += surfacenumvertices;
8875 numtriangles += surfacenumtriangles;
8878 // generate a 16bit index array as well if possible
8879 // (in general, dynamic batches fit)
8880 if (numvertices <= 65536)
8882 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8883 for (i = 0;i < numtriangles*3;i++)
8884 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8887 // since we've copied everything, the batch now starts at 0
8888 rsurface.batchfirstvertex = 0;
8889 rsurface.batchnumvertices = batchnumvertices;
8890 rsurface.batchfirsttriangle = 0;
8891 rsurface.batchnumtriangles = batchnumtriangles;
8894 // q1bsp surfaces rendered in vertex color mode have to have colors
8895 // calculated based on lightstyles
8896 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8898 // generate color arrays for the surfaces in this list
8903 const unsigned char *lm;
8904 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8905 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8906 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8908 for (i = 0;i < texturenumsurfaces;i++)
8910 surface = texturesurfacelist[i];
8911 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8912 surfacenumvertices = surface->num_vertices;
8913 if (surface->lightmapinfo->samples)
8915 for (j = 0;j < surfacenumvertices;j++)
8917 lm = surface->lightmapinfo->samples + offsets[j];
8918 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8919 VectorScale(lm, scale, c);
8920 if (surface->lightmapinfo->styles[1] != 255)
8922 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8924 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8925 VectorMA(c, scale, lm, c);
8926 if (surface->lightmapinfo->styles[2] != 255)
8929 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8930 VectorMA(c, scale, lm, c);
8931 if (surface->lightmapinfo->styles[3] != 255)
8934 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8935 VectorMA(c, scale, lm, c);
8942 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);
8948 for (j = 0;j < surfacenumvertices;j++)
8950 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8957 // if vertices are deformed (sprite flares and things in maps, possibly
8958 // water waves, bulges and other deformations), modify the copied vertices
8960 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8962 switch (deform->deform)
8965 case Q3DEFORM_PROJECTIONSHADOW:
8966 case Q3DEFORM_TEXT0:
8967 case Q3DEFORM_TEXT1:
8968 case Q3DEFORM_TEXT2:
8969 case Q3DEFORM_TEXT3:
8970 case Q3DEFORM_TEXT4:
8971 case Q3DEFORM_TEXT5:
8972 case Q3DEFORM_TEXT6:
8973 case Q3DEFORM_TEXT7:
8976 case Q3DEFORM_AUTOSPRITE:
8977 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8978 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8979 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8980 VectorNormalize(newforward);
8981 VectorNormalize(newright);
8982 VectorNormalize(newup);
8983 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8984 // rsurface.batchvertex3f_vertexbuffer = NULL;
8985 // rsurface.batchvertex3f_bufferoffset = 0;
8986 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8987 // rsurface.batchsvector3f_vertexbuffer = NULL;
8988 // rsurface.batchsvector3f_bufferoffset = 0;
8989 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8990 // rsurface.batchtvector3f_vertexbuffer = NULL;
8991 // rsurface.batchtvector3f_bufferoffset = 0;
8992 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8993 // rsurface.batchnormal3f_vertexbuffer = NULL;
8994 // rsurface.batchnormal3f_bufferoffset = 0;
8995 // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
8996 if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
8997 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8998 if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
8999 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);
9000 // a single autosprite surface can contain multiple sprites...
9001 for (j = 0;j < batchnumvertices - 3;j += 4)
9003 VectorClear(center);
9004 for (i = 0;i < 4;i++)
9005 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9006 VectorScale(center, 0.25f, center);
9007 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9008 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9009 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9010 for (i = 0;i < 4;i++)
9012 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9013 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9016 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9017 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9018 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);
9020 case Q3DEFORM_AUTOSPRITE2:
9021 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9022 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9023 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9024 VectorNormalize(newforward);
9025 VectorNormalize(newright);
9026 VectorNormalize(newup);
9027 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9028 // rsurface.batchvertex3f_vertexbuffer = NULL;
9029 // rsurface.batchvertex3f_bufferoffset = 0;
9031 const float *v1, *v2;
9041 memset(shortest, 0, sizeof(shortest));
9042 // a single autosprite surface can contain multiple sprites...
9043 for (j = 0;j < batchnumvertices - 3;j += 4)
9045 VectorClear(center);
9046 for (i = 0;i < 4;i++)
9047 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9048 VectorScale(center, 0.25f, center);
9049 // find the two shortest edges, then use them to define the
9050 // axis vectors for rotating around the central axis
9051 for (i = 0;i < 6;i++)
9053 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9054 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9055 l = VectorDistance2(v1, v2);
9056 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9058 l += (1.0f / 1024.0f);
9059 if (shortest[0].length2 > l || i == 0)
9061 shortest[1] = shortest[0];
9062 shortest[0].length2 = l;
9063 shortest[0].v1 = v1;
9064 shortest[0].v2 = v2;
9066 else if (shortest[1].length2 > l || i == 1)
9068 shortest[1].length2 = l;
9069 shortest[1].v1 = v1;
9070 shortest[1].v2 = v2;
9073 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9074 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9075 // this calculates the right vector from the shortest edge
9076 // and the up vector from the edge midpoints
9077 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9078 VectorNormalize(right);
9079 VectorSubtract(end, start, up);
9080 VectorNormalize(up);
9081 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9082 VectorSubtract(rsurface.localvieworigin, center, forward);
9083 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9084 VectorNegate(forward, forward);
9085 VectorReflect(forward, 0, up, forward);
9086 VectorNormalize(forward);
9087 CrossProduct(up, forward, newright);
9088 VectorNormalize(newright);
9089 // rotate the quad around the up axis vector, this is made
9090 // especially easy by the fact we know the quad is flat,
9091 // so we only have to subtract the center position and
9092 // measure distance along the right vector, and then
9093 // multiply that by the newright vector and add back the
9095 // we also need to subtract the old position to undo the
9096 // displacement from the center, which we do with a
9097 // DotProduct, the subtraction/addition of center is also
9098 // optimized into DotProducts here
9099 l = DotProduct(right, center);
9100 for (i = 0;i < 4;i++)
9102 v1 = rsurface.batchvertex3f + 3*(j+i);
9103 f = DotProduct(right, v1) - l;
9104 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9108 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9110 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9111 // rsurface.batchnormal3f_vertexbuffer = NULL;
9112 // rsurface.batchnormal3f_bufferoffset = 0;
9113 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9115 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9117 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9118 // rsurface.batchsvector3f_vertexbuffer = NULL;
9119 // rsurface.batchsvector3f_bufferoffset = 0;
9120 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9121 // rsurface.batchtvector3f_vertexbuffer = NULL;
9122 // rsurface.batchtvector3f_bufferoffset = 0;
9123 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);
9126 case Q3DEFORM_NORMAL:
9127 // deform the normals to make reflections wavey
9128 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9129 rsurface.batchnormal3f_vertexbuffer = NULL;
9130 rsurface.batchnormal3f_bufferoffset = 0;
9131 for (j = 0;j < batchnumvertices;j++)
9134 float *normal = rsurface.batchnormal3f + 3*j;
9135 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9136 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9137 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9138 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9139 VectorNormalize(normal);
9141 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9143 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9144 // rsurface.batchsvector3f_vertexbuffer = NULL;
9145 // rsurface.batchsvector3f_bufferoffset = 0;
9146 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9147 // rsurface.batchtvector3f_vertexbuffer = NULL;
9148 // rsurface.batchtvector3f_bufferoffset = 0;
9149 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);
9153 // deform vertex array to make wavey water and flags and such
9154 waveparms[0] = deform->waveparms[0];
9155 waveparms[1] = deform->waveparms[1];
9156 waveparms[2] = deform->waveparms[2];
9157 waveparms[3] = deform->waveparms[3];
9158 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9159 break; // if wavefunc is a nop, don't make a dynamic vertex array
9160 // this is how a divisor of vertex influence on deformation
9161 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9162 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9163 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9164 // rsurface.batchvertex3f_vertexbuffer = NULL;
9165 // rsurface.batchvertex3f_bufferoffset = 0;
9166 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9167 // rsurface.batchnormal3f_vertexbuffer = NULL;
9168 // rsurface.batchnormal3f_bufferoffset = 0;
9169 for (j = 0;j < batchnumvertices;j++)
9171 // if the wavefunc depends on time, evaluate it per-vertex
9174 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9175 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9177 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9179 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9180 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9181 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9183 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9184 // rsurface.batchsvector3f_vertexbuffer = NULL;
9185 // rsurface.batchsvector3f_bufferoffset = 0;
9186 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9187 // rsurface.batchtvector3f_vertexbuffer = NULL;
9188 // rsurface.batchtvector3f_bufferoffset = 0;
9189 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);
9192 case Q3DEFORM_BULGE:
9193 // deform vertex array to make the surface have moving bulges
9194 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9195 // rsurface.batchvertex3f_vertexbuffer = NULL;
9196 // rsurface.batchvertex3f_bufferoffset = 0;
9197 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9198 // rsurface.batchnormal3f_vertexbuffer = NULL;
9199 // rsurface.batchnormal3f_bufferoffset = 0;
9200 for (j = 0;j < batchnumvertices;j++)
9202 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9203 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9205 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9206 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9207 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9209 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9210 // rsurface.batchsvector3f_vertexbuffer = NULL;
9211 // rsurface.batchsvector3f_bufferoffset = 0;
9212 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9213 // rsurface.batchtvector3f_vertexbuffer = NULL;
9214 // rsurface.batchtvector3f_bufferoffset = 0;
9215 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);
9219 // deform vertex array
9220 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9221 break; // if wavefunc is a nop, don't make a dynamic vertex array
9222 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9223 VectorScale(deform->parms, scale, waveparms);
9224 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9225 // rsurface.batchvertex3f_vertexbuffer = NULL;
9226 // rsurface.batchvertex3f_bufferoffset = 0;
9227 for (j = 0;j < batchnumvertices;j++)
9228 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9233 // generate texcoords based on the chosen texcoord source
9234 switch(rsurface.texture->tcgen.tcgen)
9237 case Q3TCGEN_TEXTURE:
9239 case Q3TCGEN_LIGHTMAP:
9240 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9241 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9242 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9243 if (rsurface.batchtexcoordlightmap2f)
9244 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9246 case Q3TCGEN_VECTOR:
9247 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9248 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9249 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9250 for (j = 0;j < batchnumvertices;j++)
9252 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9253 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9256 case Q3TCGEN_ENVIRONMENT:
9257 // make environment reflections using a spheremap
9258 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9259 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9260 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9261 for (j = 0;j < batchnumvertices;j++)
9263 // identical to Q3A's method, but executed in worldspace so
9264 // carried models can be shiny too
9266 float viewer[3], d, reflected[3], worldreflected[3];
9268 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9269 // VectorNormalize(viewer);
9271 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9273 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9274 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9275 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9276 // note: this is proportinal to viewer, so we can normalize later
9278 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9279 VectorNormalize(worldreflected);
9281 // note: this sphere map only uses world x and z!
9282 // so positive and negative y will LOOK THE SAME.
9283 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9284 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9288 // the only tcmod that needs software vertex processing is turbulent, so
9289 // check for it here and apply the changes if needed
9290 // and we only support that as the first one
9291 // (handling a mixture of turbulent and other tcmods would be problematic
9292 // without punting it entirely to a software path)
9293 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9295 amplitude = rsurface.texture->tcmods[0].parms[1];
9296 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9297 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9298 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9299 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9300 for (j = 0;j < batchnumvertices;j++)
9302 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);
9303 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9307 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9309 // convert the modified arrays to vertex structs
9310 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9311 // rsurface.batchvertexmeshbuffer = NULL;
9312 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9313 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9314 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9315 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9316 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9317 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9318 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9320 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9322 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9323 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9326 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9327 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9328 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9329 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9330 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9331 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9332 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9333 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9334 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9338 void RSurf_DrawBatch(void)
9340 // sometimes a zero triangle surface (usually a degenerate patch) makes it
9341 // through the pipeline, killing it earlier in the pipeline would have
9342 // per-surface overhead rather than per-batch overhead, so it's best to
9343 // reject it here, before it hits glDraw.
9344 if (rsurface.batchnumtriangles == 0)
9347 // batch debugging code
9348 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9354 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9355 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9358 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9360 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9362 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9363 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);
9370 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);
9373 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9375 // pick the closest matching water plane
9376 int planeindex, vertexindex, bestplaneindex = -1;
9380 r_waterstate_waterplane_t *p;
9381 qboolean prepared = false;
9383 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
9385 if(p->camera_entity != rsurface.texture->camera_entity)
9390 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9392 if(rsurface.batchnumvertices == 0)
9395 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9397 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9398 d += fabs(PlaneDiff(vert, &p->plane));
9400 if (bestd > d || bestplaneindex < 0)
9403 bestplaneindex = planeindex;
9406 return bestplaneindex;
9407 // NOTE: this MAY return a totally unrelated water plane; we can ignore
9408 // this situation though, as it might be better to render single larger
9409 // batches with useless stuff (backface culled for example) than to
9410 // render multiple smaller batches
9413 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9416 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9417 rsurface.passcolor4f_vertexbuffer = 0;
9418 rsurface.passcolor4f_bufferoffset = 0;
9419 for (i = 0;i < rsurface.batchnumvertices;i++)
9420 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9423 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9430 if (rsurface.passcolor4f)
9432 // generate color arrays
9433 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9434 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9435 rsurface.passcolor4f_vertexbuffer = 0;
9436 rsurface.passcolor4f_bufferoffset = 0;
9437 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)
9439 f = RSurf_FogVertex(v);
9448 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9449 rsurface.passcolor4f_vertexbuffer = 0;
9450 rsurface.passcolor4f_bufferoffset = 0;
9451 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9453 f = RSurf_FogVertex(v);
9462 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9469 if (!rsurface.passcolor4f)
9471 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9472 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9473 rsurface.passcolor4f_vertexbuffer = 0;
9474 rsurface.passcolor4f_bufferoffset = 0;
9475 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)
9477 f = RSurf_FogVertex(v);
9478 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9479 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9480 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9485 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9490 if (!rsurface.passcolor4f)
9492 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9493 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9494 rsurface.passcolor4f_vertexbuffer = 0;
9495 rsurface.passcolor4f_bufferoffset = 0;
9496 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9505 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9510 if (!rsurface.passcolor4f)
9512 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9513 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9514 rsurface.passcolor4f_vertexbuffer = 0;
9515 rsurface.passcolor4f_bufferoffset = 0;
9516 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9518 c2[0] = c[0] + r_refdef.scene.ambient;
9519 c2[1] = c[1] + r_refdef.scene.ambient;
9520 c2[2] = c[2] + r_refdef.scene.ambient;
9525 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9528 rsurface.passcolor4f = NULL;
9529 rsurface.passcolor4f_vertexbuffer = 0;
9530 rsurface.passcolor4f_bufferoffset = 0;
9531 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9532 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9533 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9534 GL_Color(r, g, b, a);
9535 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9539 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9541 // TODO: optimize applyfog && applycolor case
9542 // just apply fog if necessary, and tint the fog color array if necessary
9543 rsurface.passcolor4f = NULL;
9544 rsurface.passcolor4f_vertexbuffer = 0;
9545 rsurface.passcolor4f_bufferoffset = 0;
9546 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9547 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9548 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9549 GL_Color(r, g, b, a);
9553 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9556 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9557 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9558 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9559 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9560 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9561 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9562 GL_Color(r, g, b, a);
9566 static void RSurf_DrawBatch_GL11_ClampColor(void)
9571 if (!rsurface.passcolor4f)
9573 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9575 c2[0] = bound(0.0f, c1[0], 1.0f);
9576 c2[1] = bound(0.0f, c1[1], 1.0f);
9577 c2[2] = bound(0.0f, c1[2], 1.0f);
9578 c2[3] = bound(0.0f, c1[3], 1.0f);
9582 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9592 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9593 rsurface.passcolor4f_vertexbuffer = 0;
9594 rsurface.passcolor4f_bufferoffset = 0;
9595 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)
9597 f = -DotProduct(r_refdef.view.forward, n);
9599 f = f * 0.85 + 0.15; // work around so stuff won't get black
9600 f *= r_refdef.lightmapintensity;
9601 Vector4Set(c, f, f, f, 1);
9605 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9607 RSurf_DrawBatch_GL11_ApplyFakeLight();
9608 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9609 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9610 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9611 GL_Color(r, g, b, a);
9615 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9623 vec3_t ambientcolor;
9624 vec3_t diffusecolor;
9628 VectorCopy(rsurface.modellight_lightdir, lightdir);
9629 f = 0.5f * r_refdef.lightmapintensity;
9630 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9631 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9632 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9633 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9634 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9635 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9637 if (VectorLength2(diffusecolor) > 0)
9639 // q3-style directional shading
9640 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9641 rsurface.passcolor4f_vertexbuffer = 0;
9642 rsurface.passcolor4f_bufferoffset = 0;
9643 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)
9645 if ((f = DotProduct(n, lightdir)) > 0)
9646 VectorMA(ambientcolor, f, diffusecolor, c);
9648 VectorCopy(ambientcolor, c);
9655 *applycolor = false;
9659 *r = ambientcolor[0];
9660 *g = ambientcolor[1];
9661 *b = ambientcolor[2];
9662 rsurface.passcolor4f = NULL;
9663 rsurface.passcolor4f_vertexbuffer = 0;
9664 rsurface.passcolor4f_bufferoffset = 0;
9668 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9670 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9671 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9672 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9673 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9674 GL_Color(r, g, b, a);
9678 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9686 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9687 rsurface.passcolor4f_vertexbuffer = 0;
9688 rsurface.passcolor4f_bufferoffset = 0;
9690 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9692 f = 1 - RSurf_FogVertex(v);
9700 void RSurf_SetupDepthAndCulling(void)
9702 // submodels are biased to avoid z-fighting with world surfaces that they
9703 // may be exactly overlapping (avoids z-fighting artifacts on certain
9704 // doors and things in Quake maps)
9705 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9706 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9707 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9708 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9711 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9713 // transparent sky would be ridiculous
9714 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9716 R_SetupShader_Generic_NoTexture(false, false);
9717 skyrenderlater = true;
9718 RSurf_SetupDepthAndCulling();
9720 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9721 // skymasking on them, and Quake3 never did sky masking (unlike
9722 // software Quake and software Quake2), so disable the sky masking
9723 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9724 // and skymasking also looks very bad when noclipping outside the
9725 // level, so don't use it then either.
9726 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9728 R_Mesh_ResetTextureState();
9729 if (skyrendermasked)
9731 R_SetupShader_DepthOrShadow(false, false);
9732 // depth-only (masking)
9733 GL_ColorMask(0,0,0,0);
9734 // just to make sure that braindead drivers don't draw
9735 // anything despite that colormask...
9736 GL_BlendFunc(GL_ZERO, GL_ONE);
9737 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9738 if (rsurface.batchvertex3fbuffer)
9739 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9741 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9745 R_SetupShader_Generic_NoTexture(false, false);
9747 GL_BlendFunc(GL_ONE, GL_ZERO);
9748 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9749 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9750 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9753 if (skyrendermasked)
9754 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9756 R_Mesh_ResetTextureState();
9757 GL_Color(1, 1, 1, 1);
9760 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9761 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9762 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9764 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9768 // render screenspace normalmap to texture
9770 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9775 // bind lightmap texture
9777 // water/refraction/reflection/camera surfaces have to be handled specially
9778 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9780 int start, end, startplaneindex;
9781 for (start = 0;start < texturenumsurfaces;start = end)
9783 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9784 if(startplaneindex < 0)
9786 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9787 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9791 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9793 // now that we have a batch using the same planeindex, render it
9794 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9796 // render water or distortion background
9798 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
9800 // blend surface on top
9801 GL_DepthMask(false);
9802 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9805 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9807 // render surface with reflection texture as input
9808 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9809 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
9816 // render surface batch normally
9817 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9818 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) != 0);
9822 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9824 // OpenGL 1.3 path - anything not completely ancient
9825 qboolean applycolor;
9828 const texturelayer_t *layer;
9829 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);
9830 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9832 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9835 int layertexrgbscale;
9836 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9838 if (layerindex == 0)
9842 GL_AlphaTest(false);
9843 GL_DepthFunc(GL_EQUAL);
9846 GL_DepthMask(layer->depthmask && writedepth);
9847 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9848 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9850 layertexrgbscale = 4;
9851 VectorScale(layer->color, 0.25f, layercolor);
9853 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9855 layertexrgbscale = 2;
9856 VectorScale(layer->color, 0.5f, layercolor);
9860 layertexrgbscale = 1;
9861 VectorScale(layer->color, 1.0f, layercolor);
9863 layercolor[3] = layer->color[3];
9864 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9865 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9866 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9867 switch (layer->type)
9869 case TEXTURELAYERTYPE_LITTEXTURE:
9870 // single-pass lightmapped texture with 2x rgbscale
9871 R_Mesh_TexBind(0, r_texture_white);
9872 R_Mesh_TexMatrix(0, NULL);
9873 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9874 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9875 R_Mesh_TexBind(1, layer->texture);
9876 R_Mesh_TexMatrix(1, &layer->texmatrix);
9877 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9878 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9879 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9880 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9881 else if (FAKELIGHT_ENABLED)
9882 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9883 else if (rsurface.uselightmaptexture)
9884 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9886 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9888 case TEXTURELAYERTYPE_TEXTURE:
9889 // singletexture unlit texture with transparency support
9890 R_Mesh_TexBind(0, layer->texture);
9891 R_Mesh_TexMatrix(0, &layer->texmatrix);
9892 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9893 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9894 R_Mesh_TexBind(1, 0);
9895 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9896 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9898 case TEXTURELAYERTYPE_FOG:
9899 // singletexture fogging
9902 R_Mesh_TexBind(0, layer->texture);
9903 R_Mesh_TexMatrix(0, &layer->texmatrix);
9904 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9905 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9909 R_Mesh_TexBind(0, 0);
9910 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9912 R_Mesh_TexBind(1, 0);
9913 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9914 // generate a color array for the fog pass
9915 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9916 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9920 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9923 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9925 GL_DepthFunc(GL_LEQUAL);
9926 GL_AlphaTest(false);
9930 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9932 // OpenGL 1.1 - crusty old voodoo path
9935 const texturelayer_t *layer;
9936 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);
9937 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9939 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9941 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9943 if (layerindex == 0)
9947 GL_AlphaTest(false);
9948 GL_DepthFunc(GL_EQUAL);
9951 GL_DepthMask(layer->depthmask && writedepth);
9952 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9953 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9954 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9955 switch (layer->type)
9957 case TEXTURELAYERTYPE_LITTEXTURE:
9958 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9960 // two-pass lit texture with 2x rgbscale
9961 // first the lightmap pass
9962 R_Mesh_TexBind(0, r_texture_white);
9963 R_Mesh_TexMatrix(0, NULL);
9964 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9965 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9966 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9967 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9968 else if (FAKELIGHT_ENABLED)
9969 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9970 else if (rsurface.uselightmaptexture)
9971 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9973 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9974 // then apply the texture to it
9975 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9976 R_Mesh_TexBind(0, layer->texture);
9977 R_Mesh_TexMatrix(0, &layer->texmatrix);
9978 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9979 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9980 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);
9984 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9985 R_Mesh_TexBind(0, layer->texture);
9986 R_Mesh_TexMatrix(0, &layer->texmatrix);
9987 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9988 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9989 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9990 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);
9992 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);
9995 case TEXTURELAYERTYPE_TEXTURE:
9996 // singletexture unlit texture with transparency support
9997 R_Mesh_TexBind(0, layer->texture);
9998 R_Mesh_TexMatrix(0, &layer->texmatrix);
9999 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10000 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10001 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);
10003 case TEXTURELAYERTYPE_FOG:
10004 // singletexture fogging
10005 if (layer->texture)
10007 R_Mesh_TexBind(0, layer->texture);
10008 R_Mesh_TexMatrix(0, &layer->texmatrix);
10009 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10010 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10014 R_Mesh_TexBind(0, 0);
10015 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10017 // generate a color array for the fog pass
10018 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10019 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10023 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10026 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10028 GL_DepthFunc(GL_LEQUAL);
10029 GL_AlphaTest(false);
10033 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10037 r_vertexgeneric_t *batchvertex;
10040 // R_Mesh_ResetTextureState();
10041 R_SetupShader_Generic_NoTexture(false, false);
10043 if(rsurface.texture && rsurface.texture->currentskinframe)
10045 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10046 c[3] *= rsurface.texture->currentalpha;
10056 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10058 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10059 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10060 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10063 // brighten it up (as texture value 127 means "unlit")
10064 c[0] *= 2 * r_refdef.view.colorscale;
10065 c[1] *= 2 * r_refdef.view.colorscale;
10066 c[2] *= 2 * r_refdef.view.colorscale;
10068 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10069 c[3] *= r_wateralpha.value;
10071 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10073 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10074 GL_DepthMask(false);
10076 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10078 GL_BlendFunc(GL_ONE, GL_ONE);
10079 GL_DepthMask(false);
10081 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10083 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10084 GL_DepthMask(false);
10086 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10088 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10089 GL_DepthMask(false);
10093 GL_BlendFunc(GL_ONE, GL_ZERO);
10094 GL_DepthMask(writedepth);
10097 if (r_showsurfaces.integer == 3)
10099 rsurface.passcolor4f = NULL;
10101 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10103 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10105 rsurface.passcolor4f = NULL;
10106 rsurface.passcolor4f_vertexbuffer = 0;
10107 rsurface.passcolor4f_bufferoffset = 0;
10109 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10111 qboolean applycolor = true;
10114 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10116 r_refdef.lightmapintensity = 1;
10117 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10118 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10120 else if (FAKELIGHT_ENABLED)
10122 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10124 r_refdef.lightmapintensity = r_fakelight_intensity.value;
10125 RSurf_DrawBatch_GL11_ApplyFakeLight();
10126 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10130 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10132 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10133 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10134 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10137 if(!rsurface.passcolor4f)
10138 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10140 RSurf_DrawBatch_GL11_ApplyAmbient();
10141 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10142 if(r_refdef.fogenabled)
10143 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10144 RSurf_DrawBatch_GL11_ClampColor();
10146 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10147 R_SetupShader_Generic_NoTexture(false, false);
10150 else if (!r_refdef.view.showdebug)
10152 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10153 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10154 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10156 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10157 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10159 R_Mesh_PrepareVertices_Generic_Unlock();
10162 else if (r_showsurfaces.integer == 4)
10164 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10165 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10166 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10168 unsigned char c = (vi << 3) * (1.0f / 256.0f);
10169 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10170 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10172 R_Mesh_PrepareVertices_Generic_Unlock();
10175 else if (r_showsurfaces.integer == 2)
10178 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10179 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10180 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10182 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10183 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10184 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10185 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10186 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10187 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10188 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10190 R_Mesh_PrepareVertices_Generic_Unlock();
10191 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10195 int texturesurfaceindex;
10197 const msurface_t *surface;
10198 float surfacecolor4f[4];
10199 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10200 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10202 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10204 surface = texturesurfacelist[texturesurfaceindex];
10205 k = (int)(((size_t)surface) / sizeof(msurface_t));
10206 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10207 for (j = 0;j < surface->num_vertices;j++)
10209 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10210 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10214 R_Mesh_PrepareVertices_Generic_Unlock();
10219 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10222 RSurf_SetupDepthAndCulling();
10223 if (r_showsurfaces.integer)
10225 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10228 switch (vid.renderpath)
10230 case RENDERPATH_GL20:
10231 case RENDERPATH_D3D9:
10232 case RENDERPATH_D3D10:
10233 case RENDERPATH_D3D11:
10234 case RENDERPATH_SOFT:
10235 case RENDERPATH_GLES2:
10236 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10238 case RENDERPATH_GL13:
10239 case RENDERPATH_GLES1:
10240 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10242 case RENDERPATH_GL11:
10243 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10249 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10252 RSurf_SetupDepthAndCulling();
10253 if (r_showsurfaces.integer)
10255 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10258 switch (vid.renderpath)
10260 case RENDERPATH_GL20:
10261 case RENDERPATH_D3D9:
10262 case RENDERPATH_D3D10:
10263 case RENDERPATH_D3D11:
10264 case RENDERPATH_SOFT:
10265 case RENDERPATH_GLES2:
10266 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10268 case RENDERPATH_GL13:
10269 case RENDERPATH_GLES1:
10270 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10272 case RENDERPATH_GL11:
10273 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10279 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10282 int texturenumsurfaces, endsurface;
10283 texture_t *texture;
10284 const msurface_t *surface;
10285 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10287 // if the model is static it doesn't matter what value we give for
10288 // wantnormals and wanttangents, so this logic uses only rules applicable
10289 // to a model, knowing that they are meaningless otherwise
10290 if (ent == r_refdef.scene.worldentity)
10291 RSurf_ActiveWorldEntity();
10292 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10293 RSurf_ActiveModelEntity(ent, false, false, false);
10296 switch (vid.renderpath)
10298 case RENDERPATH_GL20:
10299 case RENDERPATH_D3D9:
10300 case RENDERPATH_D3D10:
10301 case RENDERPATH_D3D11:
10302 case RENDERPATH_SOFT:
10303 case RENDERPATH_GLES2:
10304 RSurf_ActiveModelEntity(ent, true, true, false);
10306 case RENDERPATH_GL11:
10307 case RENDERPATH_GL13:
10308 case RENDERPATH_GLES1:
10309 RSurf_ActiveModelEntity(ent, true, false, false);
10314 if (r_transparentdepthmasking.integer)
10316 qboolean setup = false;
10317 for (i = 0;i < numsurfaces;i = j)
10320 surface = rsurface.modelsurfaces + surfacelist[i];
10321 texture = surface->texture;
10322 rsurface.texture = R_GetCurrentTexture(texture);
10323 rsurface.lightmaptexture = NULL;
10324 rsurface.deluxemaptexture = NULL;
10325 rsurface.uselightmaptexture = false;
10326 // scan ahead until we find a different texture
10327 endsurface = min(i + 1024, numsurfaces);
10328 texturenumsurfaces = 0;
10329 texturesurfacelist[texturenumsurfaces++] = surface;
10330 for (;j < endsurface;j++)
10332 surface = rsurface.modelsurfaces + surfacelist[j];
10333 if (texture != surface->texture)
10335 texturesurfacelist[texturenumsurfaces++] = surface;
10337 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10339 // render the range of surfaces as depth
10343 GL_ColorMask(0,0,0,0);
10345 GL_DepthTest(true);
10346 GL_BlendFunc(GL_ONE, GL_ZERO);
10347 GL_DepthMask(true);
10348 // R_Mesh_ResetTextureState();
10349 R_SetupShader_DepthOrShadow(false, false);
10351 RSurf_SetupDepthAndCulling();
10352 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10353 if (rsurface.batchvertex3fbuffer)
10354 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10356 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10360 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10363 for (i = 0;i < numsurfaces;i = j)
10366 surface = rsurface.modelsurfaces + surfacelist[i];
10367 texture = surface->texture;
10368 rsurface.texture = R_GetCurrentTexture(texture);
10369 // scan ahead until we find a different texture
10370 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10371 texturenumsurfaces = 0;
10372 texturesurfacelist[texturenumsurfaces++] = surface;
10373 if(FAKELIGHT_ENABLED)
10375 rsurface.lightmaptexture = NULL;
10376 rsurface.deluxemaptexture = NULL;
10377 rsurface.uselightmaptexture = false;
10378 for (;j < endsurface;j++)
10380 surface = rsurface.modelsurfaces + surfacelist[j];
10381 if (texture != surface->texture)
10383 texturesurfacelist[texturenumsurfaces++] = surface;
10388 rsurface.lightmaptexture = surface->lightmaptexture;
10389 rsurface.deluxemaptexture = surface->deluxemaptexture;
10390 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10391 for (;j < endsurface;j++)
10393 surface = rsurface.modelsurfaces + surfacelist[j];
10394 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10396 texturesurfacelist[texturenumsurfaces++] = surface;
10399 // render the range of surfaces
10400 if (ent == r_refdef.scene.worldentity)
10401 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10403 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10405 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10408 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10410 // transparent surfaces get pushed off into the transparent queue
10411 int surfacelistindex;
10412 const msurface_t *surface;
10413 vec3_t tempcenter, center;
10414 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10416 surface = texturesurfacelist[surfacelistindex];
10417 if (r_transparent_sortsurfacesbynearest.integer)
10419 tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
10420 tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
10421 tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
10425 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10426 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10427 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10429 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10430 if (rsurface.entity->transparent_offset) // transparent offset
10432 center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
10433 center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
10434 center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
10436 R_MeshQueue_AddTransparent((rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST) ? MESHQUEUE_SORT_HUD : ((rsurface.entity->flags & RENDER_WORLDOBJECT) ? MESHQUEUE_SORT_SKY : MESHQUEUE_SORT_DISTANCE), center, R_DrawSurface_TransparentCallback, rsurface.entity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10440 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10442 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10444 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10446 RSurf_SetupDepthAndCulling();
10447 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10448 if (rsurface.batchvertex3fbuffer)
10449 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10451 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10455 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10459 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10462 if (!rsurface.texture->currentnumlayers)
10464 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10465 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10467 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10469 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10470 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10471 else if (!rsurface.texture->currentnumlayers)
10473 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
10475 // in the deferred case, transparent surfaces were queued during prepass
10476 if (!r_shadow_usingdeferredprepass)
10477 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10481 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10482 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10487 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10490 texture_t *texture;
10491 R_FrameData_SetMark();
10492 // break the surface list down into batches by texture and use of lightmapping
10493 for (i = 0;i < numsurfaces;i = j)
10496 // texture is the base texture pointer, rsurface.texture is the
10497 // current frame/skin the texture is directing us to use (for example
10498 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10499 // use skin 1 instead)
10500 texture = surfacelist[i]->texture;
10501 rsurface.texture = R_GetCurrentTexture(texture);
10502 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10504 // if this texture is not the kind we want, skip ahead to the next one
10505 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10509 if(FAKELIGHT_ENABLED || depthonly || prepass)
10511 rsurface.lightmaptexture = NULL;
10512 rsurface.deluxemaptexture = NULL;
10513 rsurface.uselightmaptexture = false;
10514 // simply scan ahead until we find a different texture or lightmap state
10515 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10520 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10521 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10522 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10523 // simply scan ahead until we find a different texture or lightmap state
10524 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10527 // render the range of surfaces
10528 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10530 R_FrameData_ReturnToMark();
10533 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10537 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10540 if (!rsurface.texture->currentnumlayers)
10542 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10543 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10545 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10547 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10548 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10549 else if (!rsurface.texture->currentnumlayers)
10551 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
10553 // in the deferred case, transparent surfaces were queued during prepass
10554 if (!r_shadow_usingdeferredprepass)
10555 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10559 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10560 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10565 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10568 texture_t *texture;
10569 R_FrameData_SetMark();
10570 // break the surface list down into batches by texture and use of lightmapping
10571 for (i = 0;i < numsurfaces;i = j)
10574 // texture is the base texture pointer, rsurface.texture is the
10575 // current frame/skin the texture is directing us to use (for example
10576 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10577 // use skin 1 instead)
10578 texture = surfacelist[i]->texture;
10579 rsurface.texture = R_GetCurrentTexture(texture);
10580 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10582 // if this texture is not the kind we want, skip ahead to the next one
10583 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10587 if(FAKELIGHT_ENABLED || depthonly || prepass)
10589 rsurface.lightmaptexture = NULL;
10590 rsurface.deluxemaptexture = NULL;
10591 rsurface.uselightmaptexture = false;
10592 // simply scan ahead until we find a different texture or lightmap state
10593 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10598 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10599 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10600 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10601 // simply scan ahead until we find a different texture or lightmap state
10602 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10605 // render the range of surfaces
10606 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10608 R_FrameData_ReturnToMark();
10611 float locboxvertex3f[6*4*3] =
10613 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10614 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10615 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10616 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10617 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10618 1,0,0, 0,0,0, 0,1,0, 1,1,0
10621 unsigned short locboxelements[6*2*3] =
10626 12,13,14, 12,14,15,
10627 16,17,18, 16,18,19,
10631 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10634 cl_locnode_t *loc = (cl_locnode_t *)ent;
10636 float vertex3f[6*4*3];
10638 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10639 GL_DepthMask(false);
10640 GL_DepthRange(0, 1);
10641 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10642 GL_DepthTest(true);
10643 GL_CullFace(GL_NONE);
10644 R_EntityMatrix(&identitymatrix);
10646 // R_Mesh_ResetTextureState();
10648 i = surfacelist[0];
10649 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10650 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10651 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10652 surfacelist[0] < 0 ? 0.5f : 0.125f);
10654 if (VectorCompare(loc->mins, loc->maxs))
10656 VectorSet(size, 2, 2, 2);
10657 VectorMA(loc->mins, -0.5f, size, mins);
10661 VectorCopy(loc->mins, mins);
10662 VectorSubtract(loc->maxs, loc->mins, size);
10665 for (i = 0;i < 6*4*3;)
10666 for (j = 0;j < 3;j++, i++)
10667 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10669 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10670 R_SetupShader_Generic_NoTexture(false, false);
10671 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10674 void R_DrawLocs(void)
10677 cl_locnode_t *loc, *nearestloc;
10679 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10680 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10682 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10683 R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10687 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10689 if (decalsystem->decals)
10690 Mem_Free(decalsystem->decals);
10691 memset(decalsystem, 0, sizeof(*decalsystem));
10694 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)
10697 tridecal_t *decals;
10700 // expand or initialize the system
10701 if (decalsystem->maxdecals <= decalsystem->numdecals)
10703 decalsystem_t old = *decalsystem;
10704 qboolean useshortelements;
10705 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10706 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10707 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)));
10708 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10709 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10710 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10711 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10712 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10713 if (decalsystem->numdecals)
10714 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10716 Mem_Free(old.decals);
10717 for (i = 0;i < decalsystem->maxdecals*3;i++)
10718 decalsystem->element3i[i] = i;
10719 if (useshortelements)
10720 for (i = 0;i < decalsystem->maxdecals*3;i++)
10721 decalsystem->element3s[i] = i;
10724 // grab a decal and search for another free slot for the next one
10725 decals = decalsystem->decals;
10726 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10727 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10729 decalsystem->freedecal = i;
10730 if (decalsystem->numdecals <= i)
10731 decalsystem->numdecals = i + 1;
10733 // initialize the decal
10735 decal->triangleindex = triangleindex;
10736 decal->surfaceindex = surfaceindex;
10737 decal->decalsequence = decalsequence;
10738 decal->color4f[0][0] = c0[0];
10739 decal->color4f[0][1] = c0[1];
10740 decal->color4f[0][2] = c0[2];
10741 decal->color4f[0][3] = 1;
10742 decal->color4f[1][0] = c1[0];
10743 decal->color4f[1][1] = c1[1];
10744 decal->color4f[1][2] = c1[2];
10745 decal->color4f[1][3] = 1;
10746 decal->color4f[2][0] = c2[0];
10747 decal->color4f[2][1] = c2[1];
10748 decal->color4f[2][2] = c2[2];
10749 decal->color4f[2][3] = 1;
10750 decal->vertex3f[0][0] = v0[0];
10751 decal->vertex3f[0][1] = v0[1];
10752 decal->vertex3f[0][2] = v0[2];
10753 decal->vertex3f[1][0] = v1[0];
10754 decal->vertex3f[1][1] = v1[1];
10755 decal->vertex3f[1][2] = v1[2];
10756 decal->vertex3f[2][0] = v2[0];
10757 decal->vertex3f[2][1] = v2[1];
10758 decal->vertex3f[2][2] = v2[2];
10759 decal->texcoord2f[0][0] = t0[0];
10760 decal->texcoord2f[0][1] = t0[1];
10761 decal->texcoord2f[1][0] = t1[0];
10762 decal->texcoord2f[1][1] = t1[1];
10763 decal->texcoord2f[2][0] = t2[0];
10764 decal->texcoord2f[2][1] = t2[1];
10765 TriangleNormal(v0, v1, v2, decal->plane);
10766 VectorNormalize(decal->plane);
10767 decal->plane[3] = DotProduct(v0, decal->plane);
10770 extern cvar_t cl_decals_bias;
10771 extern cvar_t cl_decals_models;
10772 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10773 // baseparms, parms, temps
10774 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)
10779 const float *vertex3f;
10780 const float *normal3f;
10782 float points[2][9][3];
10789 e = rsurface.modelelement3i + 3*triangleindex;
10791 vertex3f = rsurface.modelvertex3f;
10792 normal3f = rsurface.modelnormal3f;
10796 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10798 index = 3*e[cornerindex];
10799 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10804 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10806 index = 3*e[cornerindex];
10807 VectorCopy(vertex3f + index, v[cornerindex]);
10812 //TriangleNormal(v[0], v[1], v[2], normal);
10813 //if (DotProduct(normal, localnormal) < 0.0f)
10815 // clip by each of the box planes formed from the projection matrix
10816 // if anything survives, we emit the decal
10817 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]);
10820 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]);
10823 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]);
10826 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]);
10829 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]);
10832 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]);
10835 // some part of the triangle survived, so we have to accept it...
10838 // dynamic always uses the original triangle
10840 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10842 index = 3*e[cornerindex];
10843 VectorCopy(vertex3f + index, v[cornerindex]);
10846 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10848 // convert vertex positions to texcoords
10849 Matrix4x4_Transform(projection, v[cornerindex], temp);
10850 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10851 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10852 // calculate distance fade from the projection origin
10853 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10854 f = bound(0.0f, f, 1.0f);
10855 c[cornerindex][0] = r * f;
10856 c[cornerindex][1] = g * f;
10857 c[cornerindex][2] = b * f;
10858 c[cornerindex][3] = 1.0f;
10859 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10862 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);
10864 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10865 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);
10867 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)
10869 matrix4x4_t projection;
10870 decalsystem_t *decalsystem;
10873 const msurface_t *surface;
10874 const msurface_t *surfaces;
10875 const int *surfacelist;
10876 const texture_t *texture;
10878 int numsurfacelist;
10879 int surfacelistindex;
10882 float localorigin[3];
10883 float localnormal[3];
10884 float localmins[3];
10885 float localmaxs[3];
10888 float planes[6][4];
10891 int bih_triangles_count;
10892 int bih_triangles[256];
10893 int bih_surfaces[256];
10895 decalsystem = &ent->decalsystem;
10896 model = ent->model;
10897 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10899 R_DecalSystem_Reset(&ent->decalsystem);
10903 if (!model->brush.data_leafs && !cl_decals_models.integer)
10905 if (decalsystem->model)
10906 R_DecalSystem_Reset(decalsystem);
10910 if (decalsystem->model != model)
10911 R_DecalSystem_Reset(decalsystem);
10912 decalsystem->model = model;
10914 RSurf_ActiveModelEntity(ent, true, false, false);
10916 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10917 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10918 VectorNormalize(localnormal);
10919 localsize = worldsize*rsurface.inversematrixscale;
10920 localmins[0] = localorigin[0] - localsize;
10921 localmins[1] = localorigin[1] - localsize;
10922 localmins[2] = localorigin[2] - localsize;
10923 localmaxs[0] = localorigin[0] + localsize;
10924 localmaxs[1] = localorigin[1] + localsize;
10925 localmaxs[2] = localorigin[2] + localsize;
10927 //VectorCopy(localnormal, planes[4]);
10928 //VectorVectors(planes[4], planes[2], planes[0]);
10929 AnglesFromVectors(angles, localnormal, NULL, false);
10930 AngleVectors(angles, planes[0], planes[2], planes[4]);
10931 VectorNegate(planes[0], planes[1]);
10932 VectorNegate(planes[2], planes[3]);
10933 VectorNegate(planes[4], planes[5]);
10934 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10935 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10936 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10937 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10938 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10939 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10944 matrix4x4_t forwardprojection;
10945 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10946 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10951 float projectionvector[4][3];
10952 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10953 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10954 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10955 projectionvector[0][0] = planes[0][0] * ilocalsize;
10956 projectionvector[0][1] = planes[1][0] * ilocalsize;
10957 projectionvector[0][2] = planes[2][0] * ilocalsize;
10958 projectionvector[1][0] = planes[0][1] * ilocalsize;
10959 projectionvector[1][1] = planes[1][1] * ilocalsize;
10960 projectionvector[1][2] = planes[2][1] * ilocalsize;
10961 projectionvector[2][0] = planes[0][2] * ilocalsize;
10962 projectionvector[2][1] = planes[1][2] * ilocalsize;
10963 projectionvector[2][2] = planes[2][2] * ilocalsize;
10964 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10965 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10966 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10967 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10971 dynamic = model->surfmesh.isanimated;
10972 numsurfacelist = model->nummodelsurfaces;
10973 surfacelist = model->sortedmodelsurfaces;
10974 surfaces = model->data_surfaces;
10977 bih_triangles_count = -1;
10980 if(model->render_bih.numleafs)
10981 bih = &model->render_bih;
10982 else if(model->collision_bih.numleafs)
10983 bih = &model->collision_bih;
10986 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10987 if(bih_triangles_count == 0)
10989 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10991 if(bih_triangles_count > 0)
10993 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10995 surfaceindex = bih_surfaces[triangleindex];
10996 surface = surfaces + surfaceindex;
10997 texture = surface->texture;
10998 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11000 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11002 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11007 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11009 surfaceindex = surfacelist[surfacelistindex];
11010 surface = surfaces + surfaceindex;
11011 // check cull box first because it rejects more than any other check
11012 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11014 // skip transparent surfaces
11015 texture = surface->texture;
11016 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11018 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11020 numtriangles = surface->num_triangles;
11021 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11022 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11027 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11028 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)
11030 int renderentityindex;
11031 float worldmins[3];
11032 float worldmaxs[3];
11033 entity_render_t *ent;
11035 if (!cl_decals_newsystem.integer)
11038 worldmins[0] = worldorigin[0] - worldsize;
11039 worldmins[1] = worldorigin[1] - worldsize;
11040 worldmins[2] = worldorigin[2] - worldsize;
11041 worldmaxs[0] = worldorigin[0] + worldsize;
11042 worldmaxs[1] = worldorigin[1] + worldsize;
11043 worldmaxs[2] = worldorigin[2] + worldsize;
11045 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11047 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11049 ent = r_refdef.scene.entities[renderentityindex];
11050 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11053 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11057 typedef struct r_decalsystem_splatqueue_s
11059 vec3_t worldorigin;
11060 vec3_t worldnormal;
11066 r_decalsystem_splatqueue_t;
11068 int r_decalsystem_numqueued = 0;
11069 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11071 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)
11073 r_decalsystem_splatqueue_t *queue;
11075 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11078 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11079 VectorCopy(worldorigin, queue->worldorigin);
11080 VectorCopy(worldnormal, queue->worldnormal);
11081 Vector4Set(queue->color, r, g, b, a);
11082 Vector4Set(queue->tcrange, s1, t1, s2, t2);
11083 queue->worldsize = worldsize;
11084 queue->decalsequence = cl.decalsequence++;
11087 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11090 r_decalsystem_splatqueue_t *queue;
11092 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11093 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);
11094 r_decalsystem_numqueued = 0;
11097 extern cvar_t cl_decals_max;
11098 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11101 decalsystem_t *decalsystem = &ent->decalsystem;
11108 if (!decalsystem->numdecals)
11111 if (r_showsurfaces.integer)
11114 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11116 R_DecalSystem_Reset(decalsystem);
11120 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11121 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11123 if (decalsystem->lastupdatetime)
11124 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11127 decalsystem->lastupdatetime = r_refdef.scene.time;
11128 decal = decalsystem->decals;
11129 numdecals = decalsystem->numdecals;
11131 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11133 if (decal->color4f[0][3])
11135 decal->lived += frametime;
11136 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11138 memset(decal, 0, sizeof(*decal));
11139 if (decalsystem->freedecal > i)
11140 decalsystem->freedecal = i;
11144 decal = decalsystem->decals;
11145 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11148 // collapse the array by shuffling the tail decals into the gaps
11151 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11152 decalsystem->freedecal++;
11153 if (decalsystem->freedecal == numdecals)
11155 decal[decalsystem->freedecal] = decal[--numdecals];
11158 decalsystem->numdecals = numdecals;
11160 if (numdecals <= 0)
11162 // if there are no decals left, reset decalsystem
11163 R_DecalSystem_Reset(decalsystem);
11167 extern skinframe_t *decalskinframe;
11168 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11171 decalsystem_t *decalsystem = &ent->decalsystem;
11180 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11183 numdecals = decalsystem->numdecals;
11187 if (r_showsurfaces.integer)
11190 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11192 R_DecalSystem_Reset(decalsystem);
11196 // if the model is static it doesn't matter what value we give for
11197 // wantnormals and wanttangents, so this logic uses only rules applicable
11198 // to a model, knowing that they are meaningless otherwise
11199 if (ent == r_refdef.scene.worldentity)
11200 RSurf_ActiveWorldEntity();
11202 RSurf_ActiveModelEntity(ent, false, false, false);
11204 decalsystem->lastupdatetime = r_refdef.scene.time;
11205 decal = decalsystem->decals;
11207 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11209 // update vertex positions for animated models
11210 v3f = decalsystem->vertex3f;
11211 c4f = decalsystem->color4f;
11212 t2f = decalsystem->texcoord2f;
11213 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11215 if (!decal->color4f[0][3])
11218 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11222 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11225 // update color values for fading decals
11226 if (decal->lived >= cl_decals_time.value)
11227 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11231 c4f[ 0] = decal->color4f[0][0] * alpha;
11232 c4f[ 1] = decal->color4f[0][1] * alpha;
11233 c4f[ 2] = decal->color4f[0][2] * alpha;
11235 c4f[ 4] = decal->color4f[1][0] * alpha;
11236 c4f[ 5] = decal->color4f[1][1] * alpha;
11237 c4f[ 6] = decal->color4f[1][2] * alpha;
11239 c4f[ 8] = decal->color4f[2][0] * alpha;
11240 c4f[ 9] = decal->color4f[2][1] * alpha;
11241 c4f[10] = decal->color4f[2][2] * alpha;
11244 t2f[0] = decal->texcoord2f[0][0];
11245 t2f[1] = decal->texcoord2f[0][1];
11246 t2f[2] = decal->texcoord2f[1][0];
11247 t2f[3] = decal->texcoord2f[1][1];
11248 t2f[4] = decal->texcoord2f[2][0];
11249 t2f[5] = decal->texcoord2f[2][1];
11251 // update vertex positions for animated models
11252 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11254 e = rsurface.modelelement3i + 3*decal->triangleindex;
11255 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11256 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11257 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11261 VectorCopy(decal->vertex3f[0], v3f);
11262 VectorCopy(decal->vertex3f[1], v3f + 3);
11263 VectorCopy(decal->vertex3f[2], v3f + 6);
11266 if (r_refdef.fogenabled)
11268 alpha = RSurf_FogVertex(v3f);
11269 VectorScale(c4f, alpha, c4f);
11270 alpha = RSurf_FogVertex(v3f + 3);
11271 VectorScale(c4f + 4, alpha, c4f + 4);
11272 alpha = RSurf_FogVertex(v3f + 6);
11273 VectorScale(c4f + 8, alpha, c4f + 8);
11284 r_refdef.stats.drawndecals += numtris;
11286 // now render the decals all at once
11287 // (this assumes they all use one particle font texture!)
11288 RSurf_ActiveCustomEntity(&rsurface.matrix, &rsurface.inversematrix, rsurface.ent_flags, ent->shadertime, 1, 1, 1, 1, numdecals*3, decalsystem->vertex3f, decalsystem->texcoord2f, NULL, NULL, NULL, decalsystem->color4f, numtris, decalsystem->element3i, decalsystem->element3s, false, false);
11289 // R_Mesh_ResetTextureState();
11290 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11291 GL_DepthMask(false);
11292 GL_DepthRange(0, 1);
11293 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11294 GL_DepthTest(true);
11295 GL_CullFace(GL_NONE);
11296 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11297 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
11298 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11302 static void R_DrawModelDecals(void)
11306 // fade faster when there are too many decals
11307 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11308 for (i = 0;i < r_refdef.scene.numentities;i++)
11309 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11311 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11312 for (i = 0;i < r_refdef.scene.numentities;i++)
11313 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11314 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11316 R_DecalSystem_ApplySplatEntitiesQueue();
11318 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11319 for (i = 0;i < r_refdef.scene.numentities;i++)
11320 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11322 r_refdef.stats.totaldecals += numdecals;
11324 if (r_showsurfaces.integer)
11327 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11329 for (i = 0;i < r_refdef.scene.numentities;i++)
11331 if (!r_refdef.viewcache.entityvisible[i])
11333 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11334 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11338 extern cvar_t mod_collision_bih;
11339 static void R_DrawDebugModel(void)
11341 entity_render_t *ent = rsurface.entity;
11342 int i, j, k, l, flagsmask;
11343 const msurface_t *surface;
11344 dp_model_t *model = ent->model;
11347 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11350 if (r_showoverdraw.value > 0)
11352 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11353 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11354 R_SetupShader_Generic_NoTexture(false, false);
11355 GL_DepthTest(false);
11356 GL_DepthMask(false);
11357 GL_DepthRange(0, 1);
11358 GL_BlendFunc(GL_ONE, GL_ONE);
11359 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11361 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11363 rsurface.texture = R_GetCurrentTexture(surface->texture);
11364 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11366 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11367 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11368 if (!rsurface.texture->currentlayers->depthmask)
11369 GL_Color(c, 0, 0, 1.0f);
11370 else if (ent == r_refdef.scene.worldentity)
11371 GL_Color(c, c, c, 1.0f);
11373 GL_Color(0, c, 0, 1.0f);
11374 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11378 rsurface.texture = NULL;
11381 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11383 // R_Mesh_ResetTextureState();
11384 R_SetupShader_Generic_NoTexture(false, false);
11385 GL_DepthRange(0, 1);
11386 GL_DepthTest(!r_showdisabledepthtest.integer);
11387 GL_DepthMask(false);
11388 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11390 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11394 qboolean cullbox = ent == r_refdef.scene.worldentity;
11395 const q3mbrush_t *brush;
11396 const bih_t *bih = &model->collision_bih;
11397 const bih_leaf_t *bihleaf;
11398 float vertex3f[3][3];
11399 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11401 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11403 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11405 switch (bihleaf->type)
11408 brush = model->brush.data_brushes + bihleaf->itemindex;
11409 if (brush->colbrushf && brush->colbrushf->numtriangles)
11411 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);
11412 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11413 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11416 case BIH_COLLISIONTRIANGLE:
11417 triangleindex = bihleaf->itemindex;
11418 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11419 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11420 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11421 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);
11422 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11423 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11425 case BIH_RENDERTRIANGLE:
11426 triangleindex = bihleaf->itemindex;
11427 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11428 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11429 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11430 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);
11431 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11432 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11438 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11441 if (r_showtris.integer && qglPolygonMode)
11443 if (r_showdisabledepthtest.integer)
11445 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11446 GL_DepthMask(false);
11450 GL_BlendFunc(GL_ONE, GL_ZERO);
11451 GL_DepthMask(true);
11453 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11454 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11456 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11458 rsurface.texture = R_GetCurrentTexture(surface->texture);
11459 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11461 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11462 if (!rsurface.texture->currentlayers->depthmask)
11463 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11464 else if (ent == r_refdef.scene.worldentity)
11465 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11467 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11468 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11472 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11473 rsurface.texture = NULL;
11476 if (r_shownormals.value != 0 && qglBegin)
11478 if (r_showdisabledepthtest.integer)
11480 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11481 GL_DepthMask(false);
11485 GL_BlendFunc(GL_ONE, GL_ZERO);
11486 GL_DepthMask(true);
11488 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11490 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11492 rsurface.texture = R_GetCurrentTexture(surface->texture);
11493 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11495 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11496 qglBegin(GL_LINES);
11497 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11499 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11501 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11502 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11503 qglVertex3f(v[0], v[1], v[2]);
11504 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11505 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11506 qglVertex3f(v[0], v[1], v[2]);
11509 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11511 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11513 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11514 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11515 qglVertex3f(v[0], v[1], v[2]);
11516 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11517 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11518 qglVertex3f(v[0], v[1], v[2]);
11521 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11523 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11525 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11526 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11527 qglVertex3f(v[0], v[1], v[2]);
11528 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11529 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11530 qglVertex3f(v[0], v[1], v[2]);
11533 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11535 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11537 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11538 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11539 qglVertex3f(v[0], v[1], v[2]);
11540 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11541 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11542 qglVertex3f(v[0], v[1], v[2]);
11549 rsurface.texture = NULL;
11554 int r_maxsurfacelist = 0;
11555 const msurface_t **r_surfacelist = NULL;
11556 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11558 int i, j, endj, flagsmask;
11559 dp_model_t *model = r_refdef.scene.worldmodel;
11560 msurface_t *surfaces;
11561 unsigned char *update;
11562 int numsurfacelist = 0;
11566 if (r_maxsurfacelist < model->num_surfaces)
11568 r_maxsurfacelist = model->num_surfaces;
11570 Mem_Free((msurface_t**)r_surfacelist);
11571 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11574 RSurf_ActiveWorldEntity();
11576 surfaces = model->data_surfaces;
11577 update = model->brushq1.lightmapupdateflags;
11579 // update light styles on this submodel
11580 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11582 model_brush_lightstyleinfo_t *style;
11583 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11585 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11587 int *list = style->surfacelist;
11588 style->value = r_refdef.scene.lightstylevalue[style->style];
11589 for (j = 0;j < style->numsurfaces;j++)
11590 update[list[j]] = true;
11595 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11599 R_DrawDebugModel();
11600 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11604 rsurface.lightmaptexture = NULL;
11605 rsurface.deluxemaptexture = NULL;
11606 rsurface.uselightmaptexture = false;
11607 rsurface.texture = NULL;
11608 rsurface.rtlight = NULL;
11609 numsurfacelist = 0;
11610 // add visible surfaces to draw list
11611 for (i = 0;i < model->nummodelsurfaces;i++)
11613 j = model->sortedmodelsurfaces[i];
11614 if (r_refdef.viewcache.world_surfacevisible[j])
11615 r_surfacelist[numsurfacelist++] = surfaces + j;
11617 // update lightmaps if needed
11618 if (model->brushq1.firstrender)
11620 model->brushq1.firstrender = false;
11621 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11623 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11627 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11628 if (r_refdef.viewcache.world_surfacevisible[j])
11630 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11632 // don't do anything if there were no surfaces
11633 if (!numsurfacelist)
11635 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11638 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11640 // add to stats if desired
11641 if (r_speeds.integer && !skysurfaces && !depthonly)
11643 r_refdef.stats.world_surfaces += numsurfacelist;
11644 for (j = 0;j < numsurfacelist;j++)
11645 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11648 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11651 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11653 int i, j, endj, flagsmask;
11654 dp_model_t *model = ent->model;
11655 msurface_t *surfaces;
11656 unsigned char *update;
11657 int numsurfacelist = 0;
11661 if (r_maxsurfacelist < model->num_surfaces)
11663 r_maxsurfacelist = model->num_surfaces;
11665 Mem_Free((msurface_t **)r_surfacelist);
11666 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11669 // if the model is static it doesn't matter what value we give for
11670 // wantnormals and wanttangents, so this logic uses only rules applicable
11671 // to a model, knowing that they are meaningless otherwise
11672 if (ent == r_refdef.scene.worldentity)
11673 RSurf_ActiveWorldEntity();
11674 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11675 RSurf_ActiveModelEntity(ent, false, false, false);
11677 RSurf_ActiveModelEntity(ent, true, true, true);
11678 else if (depthonly)
11680 switch (vid.renderpath)
11682 case RENDERPATH_GL20:
11683 case RENDERPATH_D3D9:
11684 case RENDERPATH_D3D10:
11685 case RENDERPATH_D3D11:
11686 case RENDERPATH_SOFT:
11687 case RENDERPATH_GLES2:
11688 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11690 case RENDERPATH_GL11:
11691 case RENDERPATH_GL13:
11692 case RENDERPATH_GLES1:
11693 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11699 switch (vid.renderpath)
11701 case RENDERPATH_GL20:
11702 case RENDERPATH_D3D9:
11703 case RENDERPATH_D3D10:
11704 case RENDERPATH_D3D11:
11705 case RENDERPATH_SOFT:
11706 case RENDERPATH_GLES2:
11707 RSurf_ActiveModelEntity(ent, true, true, false);
11709 case RENDERPATH_GL11:
11710 case RENDERPATH_GL13:
11711 case RENDERPATH_GLES1:
11712 RSurf_ActiveModelEntity(ent, true, false, false);
11717 surfaces = model->data_surfaces;
11718 update = model->brushq1.lightmapupdateflags;
11720 // update light styles
11721 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11723 model_brush_lightstyleinfo_t *style;
11724 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11726 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11728 int *list = style->surfacelist;
11729 style->value = r_refdef.scene.lightstylevalue[style->style];
11730 for (j = 0;j < style->numsurfaces;j++)
11731 update[list[j]] = true;
11736 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11740 R_DrawDebugModel();
11741 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11745 rsurface.lightmaptexture = NULL;
11746 rsurface.deluxemaptexture = NULL;
11747 rsurface.uselightmaptexture = false;
11748 rsurface.texture = NULL;
11749 rsurface.rtlight = NULL;
11750 numsurfacelist = 0;
11751 // add visible surfaces to draw list
11752 for (i = 0;i < model->nummodelsurfaces;i++)
11753 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11754 // don't do anything if there were no surfaces
11755 if (!numsurfacelist)
11757 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11760 // update lightmaps if needed
11764 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11769 R_BuildLightMap(ent, surfaces + j);
11774 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11776 R_BuildLightMap(ent, surfaces + j);
11777 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11779 // add to stats if desired
11780 if (r_speeds.integer && !skysurfaces && !depthonly)
11782 r_refdef.stats.entities_surfaces += numsurfacelist;
11783 for (j = 0;j < numsurfacelist;j++)
11784 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11787 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11790 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11792 static texture_t texture;
11793 static msurface_t surface;
11794 const msurface_t *surfacelist = &surface;
11796 // fake enough texture and surface state to render this geometry
11798 texture.update_lastrenderframe = -1; // regenerate this texture
11799 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11800 texture.currentskinframe = skinframe;
11801 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11802 texture.offsetmapping = OFFSETMAPPING_OFF;
11803 texture.offsetscale = 1;
11804 texture.specularscalemod = 1;
11805 texture.specularpowermod = 1;
11807 surface.texture = &texture;
11808 surface.num_triangles = numtriangles;
11809 surface.num_firsttriangle = firsttriangle;
11810 surface.num_vertices = numvertices;
11811 surface.num_firstvertex = firstvertex;
11814 rsurface.texture = R_GetCurrentTexture(surface.texture);
11815 rsurface.lightmaptexture = NULL;
11816 rsurface.deluxemaptexture = NULL;
11817 rsurface.uselightmaptexture = false;
11818 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11821 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)
11823 static msurface_t surface;
11824 const msurface_t *surfacelist = &surface;
11826 // fake enough texture and surface state to render this geometry
11827 surface.texture = texture;
11828 surface.num_triangles = numtriangles;
11829 surface.num_firsttriangle = firsttriangle;
11830 surface.num_vertices = numvertices;
11831 surface.num_firstvertex = firstvertex;
11834 rsurface.texture = R_GetCurrentTexture(surface.texture);
11835 rsurface.lightmaptexture = NULL;
11836 rsurface.deluxemaptexture = NULL;
11837 rsurface.uselightmaptexture = false;
11838 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);