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 - NOTE: bad performance on multi-gpu!"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
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_shadows_shadowmapbias = {CVAR_SAVE, "r_shadows_shadowmapbias", "-1", "sets shadowmap bias for fake shadows. -1 sets the value of r_shadow_shadowmapping_bias. Needs shadowmapping ON."};
124 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
125 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"};
126 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"};
127 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
128 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
129 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
130 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
131 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
132 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"};
133 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
134 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
135 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
136 cvar_t r_celshading = {CVAR_SAVE, "r_celshading", "0", "cartoon-style light shading (OpenGL 2.x only)"}; // FIXME remove OpenGL 2.x only once implemented for DX9
137 cvar_t r_celoutlines = {CVAR_SAVE, "r_celoutlines", "0", "cartoon-style outlines (requires r_shadow_deferred; OpenGL 2.x only)"}; // FIXME remove OpenGL 2.x only once implemented for DX9
139 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
140 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
141 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
142 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
143 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
144 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
145 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
146 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
148 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)"};
149 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"};
151 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
152 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
153 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
155 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"};
156 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"};
157 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"};
158 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
159 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
160 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"};
161 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)"};
162 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)"};
163 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
165 cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
166 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)"};
167 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
168 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)"};
169 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
170 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)"};
171 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)"};
172 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
173 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"};
174 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."};
175 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
176 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)"};
177 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)"};
178 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)"};
179 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)"};
180 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)"};
181 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)"};
182 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)"};
183 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)"};
185 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)"};
186 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
187 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"};
188 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
189 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
190 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
191 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"};
192 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"};
193 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)"};
195 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
196 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
197 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
198 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
200 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
201 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
203 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
204 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
205 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
206 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
207 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
208 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
210 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
211 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
212 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
213 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
214 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
215 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
216 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
217 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
218 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
219 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
221 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"};
223 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"};
225 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
227 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
229 cvar_t r_batch_multidraw = {CVAR_SAVE, "r_batch_multidraw", "1", "issue multiple glDrawElements calls when rendering a batch of surfaces with the same texture (otherwise the index data is copied to make it one draw)"};
230 cvar_t r_batch_multidraw_mintriangles = {CVAR_SAVE, "r_batch_multidraw_mintriangles", "0", "minimum number of triangles to activate multidraw path (copying small groups of triangles may be faster)"};
231 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
233 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
234 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"};
236 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, requires mod_q3shader_force_terrain_alphaflag on."};
238 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)"};
240 extern cvar_t v_glslgamma;
241 extern cvar_t v_glslgamma_2d;
243 extern qboolean v_flipped_state;
245 r_framebufferstate_t r_fb;
247 /// shadow volume bsp struct with automatically growing nodes buffer
250 rtexture_t *r_texture_blanknormalmap;
251 rtexture_t *r_texture_white;
252 rtexture_t *r_texture_grey128;
253 rtexture_t *r_texture_black;
254 rtexture_t *r_texture_notexture;
255 rtexture_t *r_texture_whitecube;
256 rtexture_t *r_texture_normalizationcube;
257 rtexture_t *r_texture_fogattenuation;
258 rtexture_t *r_texture_fogheighttexture;
259 rtexture_t *r_texture_gammaramps;
260 unsigned int r_texture_gammaramps_serial;
261 //rtexture_t *r_texture_fogintensity;
262 rtexture_t *r_texture_reflectcube;
264 // TODO: hash lookups?
265 typedef struct cubemapinfo_s
272 int r_texture_numcubemaps;
273 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
275 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
276 unsigned int r_numqueries;
277 unsigned int r_maxqueries;
279 typedef struct r_qwskincache_s
281 char name[MAX_QPATH];
282 skinframe_t *skinframe;
286 static r_qwskincache_t *r_qwskincache;
287 static int r_qwskincache_size;
289 /// vertex coordinates for a quad that covers the screen exactly
290 extern const float r_screenvertex3f[12];
291 extern const float r_d3dscreenvertex3f[12];
292 const float r_screenvertex3f[12] =
299 const float r_d3dscreenvertex3f[12] =
307 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
310 for (i = 0;i < verts;i++)
321 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
324 for (i = 0;i < verts;i++)
334 // FIXME: move this to client?
337 if (gamemode == GAME_NEHAHRA)
339 Cvar_Set("gl_fogenable", "0");
340 Cvar_Set("gl_fogdensity", "0.2");
341 Cvar_Set("gl_fogred", "0.3");
342 Cvar_Set("gl_foggreen", "0.3");
343 Cvar_Set("gl_fogblue", "0.3");
345 r_refdef.fog_density = 0;
346 r_refdef.fog_red = 0;
347 r_refdef.fog_green = 0;
348 r_refdef.fog_blue = 0;
349 r_refdef.fog_alpha = 1;
350 r_refdef.fog_start = 0;
351 r_refdef.fog_end = 16384;
352 r_refdef.fog_height = 1<<30;
353 r_refdef.fog_fadedepth = 128;
354 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
357 static void R_BuildBlankTextures(void)
359 unsigned char data[4];
360 data[2] = 128; // normal X
361 data[1] = 128; // normal Y
362 data[0] = 255; // normal Z
363 data[3] = 255; // height
364 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
369 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
374 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
379 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
382 static void R_BuildNoTexture(void)
385 unsigned char pix[16][16][4];
386 // this makes a light grey/dark grey checkerboard texture
387 for (y = 0;y < 16;y++)
389 for (x = 0;x < 16;x++)
391 if ((y < 8) ^ (x < 8))
407 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
410 static void R_BuildWhiteCube(void)
412 unsigned char data[6*1*1*4];
413 memset(data, 255, sizeof(data));
414 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
417 static void R_BuildNormalizationCube(void)
421 vec_t s, t, intensity;
424 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
425 for (side = 0;side < 6;side++)
427 for (y = 0;y < NORMSIZE;y++)
429 for (x = 0;x < NORMSIZE;x++)
431 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
432 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
467 intensity = 127.0f / sqrt(DotProduct(v, v));
468 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
469 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
470 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
471 data[((side*64+y)*64+x)*4+3] = 255;
475 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
479 static void R_BuildFogTexture(void)
483 unsigned char data1[FOGWIDTH][4];
484 //unsigned char data2[FOGWIDTH][4];
487 r_refdef.fogmasktable_start = r_refdef.fog_start;
488 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
489 r_refdef.fogmasktable_range = r_refdef.fogrange;
490 r_refdef.fogmasktable_density = r_refdef.fog_density;
492 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
493 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
495 d = (x * r - r_refdef.fogmasktable_start);
496 if(developer_extra.integer)
497 Con_DPrintf("%f ", d);
499 if (r_fog_exp2.integer)
500 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
502 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
503 if(developer_extra.integer)
504 Con_DPrintf(" : %f ", alpha);
505 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
506 if(developer_extra.integer)
507 Con_DPrintf(" = %f\n", alpha);
508 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
511 for (x = 0;x < FOGWIDTH;x++)
513 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
518 //data2[x][0] = 255 - b;
519 //data2[x][1] = 255 - b;
520 //data2[x][2] = 255 - b;
523 if (r_texture_fogattenuation)
525 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
526 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
530 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
531 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
535 static void R_BuildFogHeightTexture(void)
537 unsigned char *inpixels;
545 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
546 if (r_refdef.fogheighttexturename[0])
547 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
550 r_refdef.fog_height_tablesize = 0;
551 if (r_texture_fogheighttexture)
552 R_FreeTexture(r_texture_fogheighttexture);
553 r_texture_fogheighttexture = NULL;
554 if (r_refdef.fog_height_table2d)
555 Mem_Free(r_refdef.fog_height_table2d);
556 r_refdef.fog_height_table2d = NULL;
557 if (r_refdef.fog_height_table1d)
558 Mem_Free(r_refdef.fog_height_table1d);
559 r_refdef.fog_height_table1d = NULL;
563 r_refdef.fog_height_tablesize = size;
564 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
565 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
566 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
568 // LordHavoc: now the magic - what is that table2d for? it is a cooked
569 // average fog color table accounting for every fog layer between a point
570 // and the camera. (Note: attenuation is handled separately!)
571 for (y = 0;y < size;y++)
573 for (x = 0;x < size;x++)
579 for (j = x;j <= y;j++)
581 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
587 for (j = x;j >= y;j--)
589 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
594 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
595 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
596 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
597 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
600 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
603 //=======================================================================================================================================================
605 static const char *builtinshaderstring =
606 #include "shader_glsl.h"
609 const char *builtinhlslshaderstring =
610 #include "shader_hlsl.h"
613 char *glslshaderstring = NULL;
614 char *hlslshaderstring = NULL;
616 //=======================================================================================================================================================
618 typedef struct shaderpermutationinfo_s
623 shaderpermutationinfo_t;
625 typedef struct shadermodeinfo_s
627 const char *vertexfilename;
628 const char *geometryfilename;
629 const char *fragmentfilename;
635 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
636 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
638 {"#define USEDIFFUSE\n", " diffuse"},
639 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
640 {"#define USEVIEWTINT\n", " viewtint"},
641 {"#define USECOLORMAPPING\n", " colormapping"},
642 {"#define USESATURATION\n", " saturation"},
643 {"#define USEFOGINSIDE\n", " foginside"},
644 {"#define USEFOGOUTSIDE\n", " fogoutside"},
645 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
646 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
647 {"#define USEGAMMARAMPS\n", " gammaramps"},
648 {"#define USECUBEFILTER\n", " cubefilter"},
649 {"#define USEGLOW\n", " glow"},
650 {"#define USEBLOOM\n", " bloom"},
651 {"#define USESPECULAR\n", " specular"},
652 {"#define USEPOSTPROCESSING\n", " postprocessing"},
653 {"#define USEREFLECTION\n", " reflection"},
654 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
655 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
656 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
657 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
658 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
659 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
660 {"#define USEALPHAKILL\n", " alphakill"},
661 {"#define USEREFLECTCUBE\n", " reflectcube"},
662 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
663 {"#define USEBOUNCEGRID\n", " bouncegrid"},
664 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
665 {"#define USETRIPPY\n", " trippy"},
666 {"#define USEDEPTHRGB\n", " depthrgb"},
667 {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
668 {"#define USESKELETAL\n", " skeletal"}
671 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
672 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
674 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
675 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
676 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
677 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
678 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
679 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
680 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
681 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
682 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
683 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
684 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
685 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
686 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
687 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
688 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
689 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
690 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
691 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
694 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
696 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
697 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
698 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
699 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
700 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
701 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
702 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
703 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
704 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
705 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
706 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
707 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
708 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
709 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
710 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
711 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
712 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
713 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
716 struct r_glsl_permutation_s;
717 typedef struct r_glsl_permutation_s
720 struct r_glsl_permutation_s *hashnext;
722 unsigned int permutation;
724 /// indicates if we have tried compiling this permutation already
726 /// 0 if compilation failed
728 // texture units assigned to each detected uniform
729 int tex_Texture_First;
730 int tex_Texture_Second;
731 int tex_Texture_GammaRamps;
732 int tex_Texture_Normal;
733 int tex_Texture_Color;
734 int tex_Texture_Gloss;
735 int tex_Texture_Glow;
736 int tex_Texture_SecondaryNormal;
737 int tex_Texture_SecondaryColor;
738 int tex_Texture_SecondaryGloss;
739 int tex_Texture_SecondaryGlow;
740 int tex_Texture_Pants;
741 int tex_Texture_Shirt;
742 int tex_Texture_FogHeightTexture;
743 int tex_Texture_FogMask;
744 int tex_Texture_Lightmap;
745 int tex_Texture_Deluxemap;
746 int tex_Texture_Attenuation;
747 int tex_Texture_Cube;
748 int tex_Texture_Refraction;
749 int tex_Texture_Reflection;
750 int tex_Texture_ShadowMap2D;
751 int tex_Texture_CubeProjection;
752 int tex_Texture_ScreenNormalMap;
753 int tex_Texture_ScreenDiffuse;
754 int tex_Texture_ScreenSpecular;
755 int tex_Texture_ReflectMask;
756 int tex_Texture_ReflectCube;
757 int tex_Texture_BounceGrid;
758 /// locations of detected uniforms in program object, or -1 if not found
759 int loc_Texture_First;
760 int loc_Texture_Second;
761 int loc_Texture_GammaRamps;
762 int loc_Texture_Normal;
763 int loc_Texture_Color;
764 int loc_Texture_Gloss;
765 int loc_Texture_Glow;
766 int loc_Texture_SecondaryNormal;
767 int loc_Texture_SecondaryColor;
768 int loc_Texture_SecondaryGloss;
769 int loc_Texture_SecondaryGlow;
770 int loc_Texture_Pants;
771 int loc_Texture_Shirt;
772 int loc_Texture_FogHeightTexture;
773 int loc_Texture_FogMask;
774 int loc_Texture_Lightmap;
775 int loc_Texture_Deluxemap;
776 int loc_Texture_Attenuation;
777 int loc_Texture_Cube;
778 int loc_Texture_Refraction;
779 int loc_Texture_Reflection;
780 int loc_Texture_ShadowMap2D;
781 int loc_Texture_CubeProjection;
782 int loc_Texture_ScreenNormalMap;
783 int loc_Texture_ScreenDiffuse;
784 int loc_Texture_ScreenSpecular;
785 int loc_Texture_ReflectMask;
786 int loc_Texture_ReflectCube;
787 int loc_Texture_BounceGrid;
789 int loc_BloomBlur_Parameters;
791 int loc_Color_Ambient;
792 int loc_Color_Diffuse;
793 int loc_Color_Specular;
797 int loc_DeferredColor_Ambient;
798 int loc_DeferredColor_Diffuse;
799 int loc_DeferredColor_Specular;
800 int loc_DeferredMod_Diffuse;
801 int loc_DeferredMod_Specular;
802 int loc_DistortScaleRefractReflect;
805 int loc_FogHeightFade;
807 int loc_FogPlaneViewDist;
808 int loc_FogRangeRecip;
811 int loc_LightPosition;
812 int loc_OffsetMapping_ScaleSteps;
813 int loc_OffsetMapping_LodDistance;
814 int loc_OffsetMapping_Bias;
816 int loc_ReflectColor;
817 int loc_ReflectFactor;
818 int loc_ReflectOffset;
819 int loc_RefractColor;
821 int loc_ScreenCenterRefractReflect;
822 int loc_ScreenScaleRefractReflect;
823 int loc_ScreenToDepth;
824 int loc_ShadowMap_Parameters;
825 int loc_ShadowMap_TextureScale;
826 int loc_SpecularPower;
827 int loc_Skeletal_Transform12;
832 int loc_ViewTintColor;
834 int loc_ModelToLight;
836 int loc_BackgroundTexMatrix;
837 int loc_ModelViewProjectionMatrix;
838 int loc_ModelViewMatrix;
839 int loc_PixelToScreenTexCoord;
840 int loc_ModelToReflectCube;
841 int loc_ShadowMapMatrix;
842 int loc_BloomColorSubtract;
843 int loc_NormalmapScrollBlend;
844 int loc_BounceGridMatrix;
845 int loc_BounceGridIntensity;
847 r_glsl_permutation_t;
849 #define SHADERPERMUTATION_HASHSIZE 256
852 // non-degradable "lightweight" shader parameters to keep the permutations simpler
853 // these can NOT degrade! only use for simple stuff
856 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
857 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
858 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
859 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
860 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
861 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
862 SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
863 SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7, ///< LOD for offsetmapping
864 SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
865 SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
866 SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
867 SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
868 SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
870 #define SHADERSTATICPARMS_COUNT 13
872 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
873 static int shaderstaticparms_count = 0;
875 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
876 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
878 extern qboolean r_shadow_shadowmapsampler;
879 extern int r_shadow_shadowmappcf;
880 qboolean R_CompileShader_CheckStaticParms(void)
882 static int r_compileshader_staticparms_save[1];
883 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
884 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
887 if (r_glsl_saturation_redcompensate.integer)
888 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
889 if (r_glsl_vertextextureblend_usebothalphas.integer)
890 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
891 if (r_shadow_glossexact.integer)
892 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
893 if (r_glsl_postprocess.integer)
895 if (r_glsl_postprocess_uservec1_enable.integer)
896 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
897 if (r_glsl_postprocess_uservec2_enable.integer)
898 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
899 if (r_glsl_postprocess_uservec3_enable.integer)
900 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
901 if (r_glsl_postprocess_uservec4_enable.integer)
902 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
904 if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
905 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
907 if (r_shadow_shadowmapsampler)
908 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
909 if (r_shadow_shadowmappcf > 1)
910 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
911 else if (r_shadow_shadowmappcf)
912 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
913 if (r_celshading.integer)
914 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
915 if (r_celoutlines.integer)
916 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
918 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
921 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
922 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
923 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
925 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
926 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
928 shaderstaticparms_count = 0;
931 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
932 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
933 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
934 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
935 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
936 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
937 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
938 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
939 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
940 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
941 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
942 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
943 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
946 /// information about each possible shader permutation
947 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
948 /// currently selected permutation
949 r_glsl_permutation_t *r_glsl_permutation;
950 /// storage for permutations linked in the hash table
951 memexpandablearray_t r_glsl_permutationarray;
953 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
955 //unsigned int hashdepth = 0;
956 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
957 r_glsl_permutation_t *p;
958 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
960 if (p->mode == mode && p->permutation == permutation)
962 //if (hashdepth > 10)
963 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
968 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
970 p->permutation = permutation;
971 p->hashnext = r_glsl_permutationhash[mode][hashindex];
972 r_glsl_permutationhash[mode][hashindex] = p;
973 //if (hashdepth > 10)
974 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
978 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
981 if (!filename || !filename[0])
983 if (!strcmp(filename, "glsl/default.glsl"))
985 if (!glslshaderstring)
987 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
988 if (glslshaderstring)
989 Con_DPrintf("Loading shaders from file %s...\n", filename);
991 glslshaderstring = (char *)builtinshaderstring;
993 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
994 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
997 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1000 if (printfromdisknotice)
1001 Con_DPrintf("from disk %s... ", filename);
1002 return shaderstring;
1004 return shaderstring;
1007 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1011 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1012 char *vertexstring, *geometrystring, *fragmentstring;
1013 char permutationname[256];
1014 int vertstrings_count = 0;
1015 int geomstrings_count = 0;
1016 int fragstrings_count = 0;
1017 const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1018 const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1019 const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1026 permutationname[0] = 0;
1027 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1028 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1029 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1031 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1033 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1034 if(vid.support.gl20shaders130)
1036 vertstrings_list[vertstrings_count++] = "#version 130\n";
1037 geomstrings_list[geomstrings_count++] = "#version 130\n";
1038 fragstrings_list[fragstrings_count++] = "#version 130\n";
1039 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1040 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1041 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1044 // the first pretext is which type of shader to compile as
1045 // (later these will all be bound together as a program object)
1046 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1047 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1048 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1050 // the second pretext is the mode (for example a light source)
1051 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1052 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1053 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1054 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1056 // now add all the permutation pretexts
1057 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1059 if (permutation & (1<<i))
1061 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1062 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1063 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1064 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1068 // keep line numbers correct
1069 vertstrings_list[vertstrings_count++] = "\n";
1070 geomstrings_list[geomstrings_count++] = "\n";
1071 fragstrings_list[fragstrings_count++] = "\n";
1076 R_CompileShader_AddStaticParms(mode, permutation);
1077 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1078 vertstrings_count += shaderstaticparms_count;
1079 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1080 geomstrings_count += shaderstaticparms_count;
1081 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1082 fragstrings_count += shaderstaticparms_count;
1084 // now append the shader text itself
1085 vertstrings_list[vertstrings_count++] = vertexstring;
1086 geomstrings_list[geomstrings_count++] = geometrystring;
1087 fragstrings_list[fragstrings_count++] = fragmentstring;
1089 // if any sources were NULL, clear the respective list
1091 vertstrings_count = 0;
1092 if (!geometrystring)
1093 geomstrings_count = 0;
1094 if (!fragmentstring)
1095 fragstrings_count = 0;
1097 // compile the shader program
1098 if (vertstrings_count + geomstrings_count + fragstrings_count)
1099 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1103 qglUseProgram(p->program);CHECKGLERROR
1104 // look up all the uniform variable names we care about, so we don't
1105 // have to look them up every time we set them
1107 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1108 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1109 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1110 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1111 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1112 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1113 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1114 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1115 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1116 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1117 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1118 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1119 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1120 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1121 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1122 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1123 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1124 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1125 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1126 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1127 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1128 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1129 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1130 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1131 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1132 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1133 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1134 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1135 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1136 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1137 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1138 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1139 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1140 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1141 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1142 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1143 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1144 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1145 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1146 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1147 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1148 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1149 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1150 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1151 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1152 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1153 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1154 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1155 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1156 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1157 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1158 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1159 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1160 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1161 p->loc_OffsetMapping_LodDistance = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1162 p->loc_OffsetMapping_Bias = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1163 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1164 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1165 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1166 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1167 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1168 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1169 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1170 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1171 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1172 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1173 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1174 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1175 p->loc_Skeletal_Transform12 = qglGetUniformLocation(p->program, "Skeletal_Transform12");
1176 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1177 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1178 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1179 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1180 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1181 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1182 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1183 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1184 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1185 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1186 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1187 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1188 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1189 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1190 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1191 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1192 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1193 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1194 // initialize the samplers to refer to the texture units we use
1195 p->tex_Texture_First = -1;
1196 p->tex_Texture_Second = -1;
1197 p->tex_Texture_GammaRamps = -1;
1198 p->tex_Texture_Normal = -1;
1199 p->tex_Texture_Color = -1;
1200 p->tex_Texture_Gloss = -1;
1201 p->tex_Texture_Glow = -1;
1202 p->tex_Texture_SecondaryNormal = -1;
1203 p->tex_Texture_SecondaryColor = -1;
1204 p->tex_Texture_SecondaryGloss = -1;
1205 p->tex_Texture_SecondaryGlow = -1;
1206 p->tex_Texture_Pants = -1;
1207 p->tex_Texture_Shirt = -1;
1208 p->tex_Texture_FogHeightTexture = -1;
1209 p->tex_Texture_FogMask = -1;
1210 p->tex_Texture_Lightmap = -1;
1211 p->tex_Texture_Deluxemap = -1;
1212 p->tex_Texture_Attenuation = -1;
1213 p->tex_Texture_Cube = -1;
1214 p->tex_Texture_Refraction = -1;
1215 p->tex_Texture_Reflection = -1;
1216 p->tex_Texture_ShadowMap2D = -1;
1217 p->tex_Texture_CubeProjection = -1;
1218 p->tex_Texture_ScreenNormalMap = -1;
1219 p->tex_Texture_ScreenDiffuse = -1;
1220 p->tex_Texture_ScreenSpecular = -1;
1221 p->tex_Texture_ReflectMask = -1;
1222 p->tex_Texture_ReflectCube = -1;
1223 p->tex_Texture_BounceGrid = -1;
1225 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1226 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1227 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1228 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1229 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1230 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1231 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1232 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1233 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1234 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1235 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1236 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1237 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1238 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1239 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1240 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1241 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1242 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1243 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1244 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1245 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1246 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1247 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1248 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1249 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1250 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1251 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1252 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1253 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1255 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1258 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1262 Mem_Free(vertexstring);
1264 Mem_Free(geometrystring);
1266 Mem_Free(fragmentstring);
1269 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1271 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1272 if (r_glsl_permutation != perm)
1274 r_glsl_permutation = perm;
1275 if (!r_glsl_permutation->program)
1277 if (!r_glsl_permutation->compiled)
1278 R_GLSL_CompilePermutation(perm, mode, permutation);
1279 if (!r_glsl_permutation->program)
1281 // remove features until we find a valid permutation
1283 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1285 // reduce i more quickly whenever it would not remove any bits
1286 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1287 if (!(permutation & j))
1290 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1291 if (!r_glsl_permutation->compiled)
1292 R_GLSL_CompilePermutation(perm, mode, permutation);
1293 if (r_glsl_permutation->program)
1296 if (i >= SHADERPERMUTATION_COUNT)
1298 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1299 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1300 qglUseProgram(0);CHECKGLERROR
1301 return; // no bit left to clear, entire mode is broken
1306 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1308 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1309 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1310 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1317 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1318 extern D3DCAPS9 vid_d3d9caps;
1321 struct r_hlsl_permutation_s;
1322 typedef struct r_hlsl_permutation_s
1324 /// hash lookup data
1325 struct r_hlsl_permutation_s *hashnext;
1327 unsigned int permutation;
1329 /// indicates if we have tried compiling this permutation already
1331 /// NULL if compilation failed
1332 IDirect3DVertexShader9 *vertexshader;
1333 IDirect3DPixelShader9 *pixelshader;
1335 r_hlsl_permutation_t;
1337 typedef enum D3DVSREGISTER_e
1339 D3DVSREGISTER_TexMatrix = 0, // float4x4
1340 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1341 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1342 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1343 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1344 D3DVSREGISTER_ModelToLight = 20, // float4x4
1345 D3DVSREGISTER_EyePosition = 24,
1346 D3DVSREGISTER_FogPlane = 25,
1347 D3DVSREGISTER_LightDir = 26,
1348 D3DVSREGISTER_LightPosition = 27,
1352 typedef enum D3DPSREGISTER_e
1354 D3DPSREGISTER_Alpha = 0,
1355 D3DPSREGISTER_BloomBlur_Parameters = 1,
1356 D3DPSREGISTER_ClientTime = 2,
1357 D3DPSREGISTER_Color_Ambient = 3,
1358 D3DPSREGISTER_Color_Diffuse = 4,
1359 D3DPSREGISTER_Color_Specular = 5,
1360 D3DPSREGISTER_Color_Glow = 6,
1361 D3DPSREGISTER_Color_Pants = 7,
1362 D3DPSREGISTER_Color_Shirt = 8,
1363 D3DPSREGISTER_DeferredColor_Ambient = 9,
1364 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1365 D3DPSREGISTER_DeferredColor_Specular = 11,
1366 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1367 D3DPSREGISTER_DeferredMod_Specular = 13,
1368 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1369 D3DPSREGISTER_EyePosition = 15, // unused
1370 D3DPSREGISTER_FogColor = 16,
1371 D3DPSREGISTER_FogHeightFade = 17,
1372 D3DPSREGISTER_FogPlane = 18,
1373 D3DPSREGISTER_FogPlaneViewDist = 19,
1374 D3DPSREGISTER_FogRangeRecip = 20,
1375 D3DPSREGISTER_LightColor = 21,
1376 D3DPSREGISTER_LightDir = 22, // unused
1377 D3DPSREGISTER_LightPosition = 23,
1378 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1379 D3DPSREGISTER_PixelSize = 25,
1380 D3DPSREGISTER_ReflectColor = 26,
1381 D3DPSREGISTER_ReflectFactor = 27,
1382 D3DPSREGISTER_ReflectOffset = 28,
1383 D3DPSREGISTER_RefractColor = 29,
1384 D3DPSREGISTER_Saturation = 30,
1385 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1386 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1387 D3DPSREGISTER_ScreenToDepth = 33,
1388 D3DPSREGISTER_ShadowMap_Parameters = 34,
1389 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1390 D3DPSREGISTER_SpecularPower = 36,
1391 D3DPSREGISTER_UserVec1 = 37,
1392 D3DPSREGISTER_UserVec2 = 38,
1393 D3DPSREGISTER_UserVec3 = 39,
1394 D3DPSREGISTER_UserVec4 = 40,
1395 D3DPSREGISTER_ViewTintColor = 41,
1396 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1397 D3DPSREGISTER_BloomColorSubtract = 43,
1398 D3DPSREGISTER_ViewToLight = 44, // float4x4
1399 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1400 D3DPSREGISTER_NormalmapScrollBlend = 52,
1401 D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1402 D3DPSREGISTER_OffsetMapping_Bias = 54,
1407 /// information about each possible shader permutation
1408 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1409 /// currently selected permutation
1410 r_hlsl_permutation_t *r_hlsl_permutation;
1411 /// storage for permutations linked in the hash table
1412 memexpandablearray_t r_hlsl_permutationarray;
1414 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1416 //unsigned int hashdepth = 0;
1417 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1418 r_hlsl_permutation_t *p;
1419 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1421 if (p->mode == mode && p->permutation == permutation)
1423 //if (hashdepth > 10)
1424 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1429 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1431 p->permutation = permutation;
1432 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1433 r_hlsl_permutationhash[mode][hashindex] = p;
1434 //if (hashdepth > 10)
1435 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1439 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1442 if (!filename || !filename[0])
1444 if (!strcmp(filename, "hlsl/default.hlsl"))
1446 if (!hlslshaderstring)
1448 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1449 if (hlslshaderstring)
1450 Con_DPrintf("Loading shaders from file %s...\n", filename);
1452 hlslshaderstring = (char *)builtinhlslshaderstring;
1454 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1455 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1456 return shaderstring;
1458 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1461 if (printfromdisknotice)
1462 Con_DPrintf("from disk %s... ", filename);
1463 return shaderstring;
1465 return shaderstring;
1469 //#include <d3dx9shader.h>
1470 //#include <d3dx9mesh.h>
1472 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1474 DWORD *vsbin = NULL;
1475 DWORD *psbin = NULL;
1476 fs_offset_t vsbinsize;
1477 fs_offset_t psbinsize;
1478 // IDirect3DVertexShader9 *vs = NULL;
1479 // IDirect3DPixelShader9 *ps = NULL;
1480 ID3DXBuffer *vslog = NULL;
1481 ID3DXBuffer *vsbuffer = NULL;
1482 ID3DXConstantTable *vsconstanttable = NULL;
1483 ID3DXBuffer *pslog = NULL;
1484 ID3DXBuffer *psbuffer = NULL;
1485 ID3DXConstantTable *psconstanttable = NULL;
1488 char temp[MAX_INPUTLINE];
1489 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1491 qboolean debugshader = gl_paranoid.integer != 0;
1492 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1493 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1496 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1497 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1499 if ((!vsbin && vertstring) || (!psbin && fragstring))
1501 const char* dllnames_d3dx9 [] =
1525 dllhandle_t d3dx9_dll = NULL;
1526 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1527 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1528 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1529 dllfunction_t d3dx9_dllfuncs[] =
1531 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1532 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1533 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1536 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1538 DWORD shaderflags = 0;
1540 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1541 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1542 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1543 if (vertstring && vertstring[0])
1547 FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1548 vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1551 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1554 vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1555 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1556 memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1557 ID3DXBuffer_Release(vsbuffer);
1561 strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1562 Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1563 ID3DXBuffer_Release(vslog);
1566 if (fragstring && fragstring[0])
1570 FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1571 psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1574 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1577 psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1578 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1579 memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1580 ID3DXBuffer_Release(psbuffer);
1584 strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1585 Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1586 ID3DXBuffer_Release(pslog);
1589 Sys_UnloadLibrary(&d3dx9_dll);
1592 Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1596 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1597 if (FAILED(vsresult))
1598 Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1599 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1600 if (FAILED(psresult))
1601 Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1603 // free the shader data
1604 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1605 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1608 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1611 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1612 int vertstring_length = 0;
1613 int geomstring_length = 0;
1614 int fragstring_length = 0;
1616 char *vertexstring, *geometrystring, *fragmentstring;
1617 char *vertstring, *geomstring, *fragstring;
1618 char permutationname[256];
1619 char cachename[256];
1620 int vertstrings_count = 0;
1621 int geomstrings_count = 0;
1622 int fragstrings_count = 0;
1623 const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1624 const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1625 const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1630 p->vertexshader = NULL;
1631 p->pixelshader = NULL;
1633 permutationname[0] = 0;
1635 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
1636 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1637 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1639 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1640 strlcat(cachename, "hlsl/", sizeof(cachename));
1642 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1643 vertstrings_count = 0;
1644 geomstrings_count = 0;
1645 fragstrings_count = 0;
1646 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1647 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1648 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1650 // the first pretext is which type of shader to compile as
1651 // (later these will all be bound together as a program object)
1652 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1653 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1654 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1656 // the second pretext is the mode (for example a light source)
1657 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1658 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1659 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1660 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1661 strlcat(cachename, modeinfo->name, sizeof(cachename));
1663 // now add all the permutation pretexts
1664 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1666 if (permutation & (1<<i))
1668 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1669 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1670 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1671 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1672 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1676 // keep line numbers correct
1677 vertstrings_list[vertstrings_count++] = "\n";
1678 geomstrings_list[geomstrings_count++] = "\n";
1679 fragstrings_list[fragstrings_count++] = "\n";
1684 R_CompileShader_AddStaticParms(mode, permutation);
1685 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1686 vertstrings_count += shaderstaticparms_count;
1687 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1688 geomstrings_count += shaderstaticparms_count;
1689 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1690 fragstrings_count += shaderstaticparms_count;
1692 // replace spaces in the cachename with _ characters
1693 for (i = 0;cachename[i];i++)
1694 if (cachename[i] == ' ')
1697 // now append the shader text itself
1698 vertstrings_list[vertstrings_count++] = vertexstring;
1699 geomstrings_list[geomstrings_count++] = geometrystring;
1700 fragstrings_list[fragstrings_count++] = fragmentstring;
1702 // if any sources were NULL, clear the respective list
1704 vertstrings_count = 0;
1705 if (!geometrystring)
1706 geomstrings_count = 0;
1707 if (!fragmentstring)
1708 fragstrings_count = 0;
1710 vertstring_length = 0;
1711 for (i = 0;i < vertstrings_count;i++)
1712 vertstring_length += strlen(vertstrings_list[i]);
1713 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1714 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1715 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1717 geomstring_length = 0;
1718 for (i = 0;i < geomstrings_count;i++)
1719 geomstring_length += strlen(geomstrings_list[i]);
1720 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1721 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1722 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1724 fragstring_length = 0;
1725 for (i = 0;i < fragstrings_count;i++)
1726 fragstring_length += strlen(fragstrings_list[i]);
1727 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1728 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1729 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1731 // try to load the cached shader, or generate one
1732 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1734 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1735 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1737 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1741 Mem_Free(vertstring);
1743 Mem_Free(geomstring);
1745 Mem_Free(fragstring);
1747 Mem_Free(vertexstring);
1749 Mem_Free(geometrystring);
1751 Mem_Free(fragmentstring);
1754 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1755 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1756 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);}
1757 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);}
1758 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);}
1759 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);}
1761 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1762 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1763 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);}
1764 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);}
1765 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);}
1766 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);}
1768 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1770 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1771 if (r_hlsl_permutation != perm)
1773 r_hlsl_permutation = perm;
1774 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1776 if (!r_hlsl_permutation->compiled)
1777 R_HLSL_CompilePermutation(perm, mode, permutation);
1778 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1780 // remove features until we find a valid permutation
1782 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1784 // reduce i more quickly whenever it would not remove any bits
1785 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1786 if (!(permutation & j))
1789 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1790 if (!r_hlsl_permutation->compiled)
1791 R_HLSL_CompilePermutation(perm, mode, permutation);
1792 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1795 if (i >= SHADERPERMUTATION_COUNT)
1797 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1798 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1799 return; // no bit left to clear, entire mode is broken
1803 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1804 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1806 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1807 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1808 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1812 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1814 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1815 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1816 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1817 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1820 void R_GLSL_Restart_f(void)
1822 unsigned int i, limit;
1823 if (glslshaderstring && glslshaderstring != builtinshaderstring)
1824 Mem_Free(glslshaderstring);
1825 glslshaderstring = NULL;
1826 if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1827 Mem_Free(hlslshaderstring);
1828 hlslshaderstring = NULL;
1829 switch(vid.renderpath)
1831 case RENDERPATH_D3D9:
1834 r_hlsl_permutation_t *p;
1835 r_hlsl_permutation = NULL;
1836 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1837 for (i = 0;i < limit;i++)
1839 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1841 if (p->vertexshader)
1842 IDirect3DVertexShader9_Release(p->vertexshader);
1844 IDirect3DPixelShader9_Release(p->pixelshader);
1845 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1848 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1852 case RENDERPATH_D3D10:
1853 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1855 case RENDERPATH_D3D11:
1856 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1858 case RENDERPATH_GL20:
1859 case RENDERPATH_GLES2:
1861 r_glsl_permutation_t *p;
1862 r_glsl_permutation = NULL;
1863 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1864 for (i = 0;i < limit;i++)
1866 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1868 GL_Backend_FreeProgram(p->program);
1869 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1872 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1875 case RENDERPATH_GL11:
1876 case RENDERPATH_GL13:
1877 case RENDERPATH_GLES1:
1879 case RENDERPATH_SOFT:
1884 static void R_GLSL_DumpShader_f(void)
1889 file = FS_OpenRealFile("glsl/default.glsl", "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, glslshadermodeinfo[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, builtinshaderstring);
1901 Con_Printf("glsl/default.glsl written\n");
1904 Con_Printf("failed to write to glsl/default.glsl\n");
1906 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1909 FS_Print(file, "/* The engine may define the following macros:\n");
1910 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1911 for (i = 0;i < SHADERMODE_COUNT;i++)
1912 FS_Print(file, hlslshadermodeinfo[i].pretext);
1913 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1914 FS_Print(file, shaderpermutationinfo[i].pretext);
1915 FS_Print(file, "*/\n");
1916 FS_Print(file, builtinhlslshaderstring);
1918 Con_Printf("hlsl/default.hlsl written\n");
1921 Con_Printf("failed to write to hlsl/default.hlsl\n");
1924 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1926 unsigned int permutation = 0;
1927 if (r_trippy.integer && !notrippy)
1928 permutation |= SHADERPERMUTATION_TRIPPY;
1929 permutation |= SHADERPERMUTATION_VIEWTINT;
1931 permutation |= SHADERPERMUTATION_DIFFUSE;
1933 permutation |= SHADERPERMUTATION_SPECULAR;
1934 if (texturemode == GL_MODULATE)
1935 permutation |= SHADERPERMUTATION_COLORMAPPING;
1936 else if (texturemode == GL_ADD)
1937 permutation |= SHADERPERMUTATION_GLOW;
1938 else if (texturemode == GL_DECAL)
1939 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1940 if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1941 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1942 if (suppresstexalpha)
1943 permutation |= SHADERPERMUTATION_REFLECTCUBE;
1945 texturemode = GL_MODULATE;
1946 if (vid.allowalphatocoverage)
1947 GL_AlphaToCoverage(false);
1948 switch (vid.renderpath)
1950 case RENDERPATH_D3D9:
1952 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1953 R_Mesh_TexBind(GL20TU_FIRST , first );
1954 R_Mesh_TexBind(GL20TU_SECOND, second);
1955 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1956 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1959 case RENDERPATH_D3D10:
1960 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1962 case RENDERPATH_D3D11:
1963 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1965 case RENDERPATH_GL20:
1966 case RENDERPATH_GLES2:
1967 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1968 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1969 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1970 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1971 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1973 case RENDERPATH_GL13:
1974 case RENDERPATH_GLES1:
1975 R_Mesh_TexBind(0, first );
1976 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1977 R_Mesh_TexBind(1, second);
1979 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1981 case RENDERPATH_GL11:
1982 R_Mesh_TexBind(0, first );
1984 case RENDERPATH_SOFT:
1985 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1986 R_Mesh_TexBind(GL20TU_FIRST , first );
1987 R_Mesh_TexBind(GL20TU_SECOND, second);
1992 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
1994 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
1997 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
1999 unsigned int permutation = 0;
2000 if (r_trippy.integer && !notrippy)
2001 permutation |= SHADERPERMUTATION_TRIPPY;
2003 permutation |= SHADERPERMUTATION_DEPTHRGB;
2005 permutation |= SHADERPERMUTATION_SKELETAL;
2007 if (vid.allowalphatocoverage)
2008 GL_AlphaToCoverage(false);
2009 switch (vid.renderpath)
2011 case RENDERPATH_D3D9:
2013 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2016 case RENDERPATH_D3D10:
2017 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2019 case RENDERPATH_D3D11:
2020 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2022 case RENDERPATH_GL20:
2023 case RENDERPATH_GLES2:
2024 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2026 case RENDERPATH_GL13:
2027 case RENDERPATH_GLES1:
2028 R_Mesh_TexBind(0, 0);
2029 R_Mesh_TexBind(1, 0);
2031 case RENDERPATH_GL11:
2032 R_Mesh_TexBind(0, 0);
2034 case RENDERPATH_SOFT:
2035 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2040 void R_SetupShader_ShowDepth(qboolean notrippy)
2042 int permutation = 0;
2043 if (r_trippy.integer && !notrippy)
2044 permutation |= SHADERPERMUTATION_TRIPPY;
2045 if (vid.allowalphatocoverage)
2046 GL_AlphaToCoverage(false);
2047 switch (vid.renderpath)
2049 case RENDERPATH_D3D9:
2051 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2054 case RENDERPATH_D3D10:
2055 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2057 case RENDERPATH_D3D11:
2058 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2060 case RENDERPATH_GL20:
2061 case RENDERPATH_GLES2:
2062 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2064 case RENDERPATH_GL13:
2065 case RENDERPATH_GLES1:
2067 case RENDERPATH_GL11:
2069 case RENDERPATH_SOFT:
2070 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2075 extern qboolean r_shadow_usingdeferredprepass;
2076 extern rtexture_t *r_shadow_attenuationgradienttexture;
2077 extern rtexture_t *r_shadow_attenuation2dtexture;
2078 extern rtexture_t *r_shadow_attenuation3dtexture;
2079 extern qboolean r_shadow_usingshadowmap2d;
2080 extern qboolean r_shadow_usingshadowmaportho;
2081 extern float r_shadow_shadowmap_texturescale[2];
2082 extern float r_shadow_shadowmap_parameters[4];
2083 extern qboolean r_shadow_shadowmapvsdct;
2084 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2085 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2086 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2087 extern matrix4x4_t r_shadow_shadowmapmatrix;
2088 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2089 extern int r_shadow_prepass_width;
2090 extern int r_shadow_prepass_height;
2091 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2092 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2093 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2094 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2096 #define BLENDFUNC_ALLOWS_COLORMOD 1
2097 #define BLENDFUNC_ALLOWS_FOG 2
2098 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2099 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2100 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2101 static int R_BlendFuncFlags(int src, int dst)
2105 // a blendfunc allows colormod if:
2106 // a) it can never keep the destination pixel invariant, or
2107 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2108 // this is to prevent unintended side effects from colormod
2110 // a blendfunc allows fog if:
2111 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2112 // this is to prevent unintended side effects from fog
2114 // these checks are the output of fogeval.pl
2116 r |= BLENDFUNC_ALLOWS_COLORMOD;
2117 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2118 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2119 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2120 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2121 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2122 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2123 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2124 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2125 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2126 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2127 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2128 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2129 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2130 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2131 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2132 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2133 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2134 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2135 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2136 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2137 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2142 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)
2144 // select a permutation of the lighting shader appropriate to this
2145 // combination of texture, entity, light source, and fogging, only use the
2146 // minimum features necessary to avoid wasting rendering time in the
2147 // fragment shader on features that are not being used
2148 unsigned int permutation = 0;
2149 unsigned int mode = 0;
2151 static float dummy_colormod[3] = {1, 1, 1};
2152 float *colormod = rsurface.colormod;
2154 matrix4x4_t tempmatrix;
2155 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2156 if (r_trippy.integer && !notrippy)
2157 permutation |= SHADERPERMUTATION_TRIPPY;
2158 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2159 permutation |= SHADERPERMUTATION_ALPHAKILL;
2160 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2161 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2162 if (rsurfacepass == RSURFPASS_BACKGROUND)
2164 // distorted background
2165 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2167 mode = SHADERMODE_WATER;
2168 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2169 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2170 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2172 // this is the right thing to do for wateralpha
2173 GL_BlendFunc(GL_ONE, GL_ZERO);
2174 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2178 // this is the right thing to do for entity alpha
2179 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2180 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2183 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2185 mode = SHADERMODE_REFRACTION;
2186 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2187 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2188 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2189 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2193 mode = SHADERMODE_GENERIC;
2194 permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2195 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2196 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2198 if (vid.allowalphatocoverage)
2199 GL_AlphaToCoverage(false);
2201 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2203 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2205 switch(rsurface.texture->offsetmapping)
2207 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2208 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2209 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2210 case OFFSETMAPPING_OFF: break;
2213 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2214 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2215 // normalmap (deferred prepass), may use alpha test on diffuse
2216 mode = SHADERMODE_DEFERREDGEOMETRY;
2217 GL_BlendFunc(GL_ONE, GL_ZERO);
2218 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2219 if (vid.allowalphatocoverage)
2220 GL_AlphaToCoverage(false);
2222 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2224 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2226 switch(rsurface.texture->offsetmapping)
2228 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2229 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2230 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2231 case OFFSETMAPPING_OFF: break;
2234 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2235 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2236 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2237 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2239 mode = SHADERMODE_LIGHTSOURCE;
2240 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2241 permutation |= SHADERPERMUTATION_CUBEFILTER;
2242 if (diffusescale > 0)
2243 permutation |= SHADERPERMUTATION_DIFFUSE;
2244 if (specularscale > 0)
2245 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2246 if (r_refdef.fogenabled)
2247 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2248 if (rsurface.texture->colormapping)
2249 permutation |= SHADERPERMUTATION_COLORMAPPING;
2250 if (r_shadow_usingshadowmap2d)
2252 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2253 if(r_shadow_shadowmapvsdct)
2254 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2256 if (r_shadow_shadowmap2ddepthbuffer)
2257 permutation |= SHADERPERMUTATION_DEPTHRGB;
2259 if (rsurface.texture->reflectmasktexture)
2260 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2261 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2262 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2263 if (vid.allowalphatocoverage)
2264 GL_AlphaToCoverage(false);
2266 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2268 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2270 switch(rsurface.texture->offsetmapping)
2272 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2273 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2274 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2275 case OFFSETMAPPING_OFF: break;
2278 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2279 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2280 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2281 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2282 // unshaded geometry (fullbright or ambient model lighting)
2283 mode = SHADERMODE_FLATCOLOR;
2284 ambientscale = diffusescale = specularscale = 0;
2285 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2286 permutation |= SHADERPERMUTATION_GLOW;
2287 if (r_refdef.fogenabled)
2288 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2289 if (rsurface.texture->colormapping)
2290 permutation |= SHADERPERMUTATION_COLORMAPPING;
2291 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2293 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2294 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2296 if (r_shadow_shadowmap2ddepthbuffer)
2297 permutation |= SHADERPERMUTATION_DEPTHRGB;
2299 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2300 permutation |= SHADERPERMUTATION_REFLECTION;
2301 if (rsurface.texture->reflectmasktexture)
2302 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2303 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2304 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2305 // when using alphatocoverage, we don't need alphakill
2306 if (vid.allowalphatocoverage)
2308 if (r_transparent_alphatocoverage.integer)
2310 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2311 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2314 GL_AlphaToCoverage(false);
2317 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2319 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2321 switch(rsurface.texture->offsetmapping)
2323 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2324 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2325 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2326 case OFFSETMAPPING_OFF: break;
2329 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2330 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2331 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2332 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2333 // directional model lighting
2334 mode = SHADERMODE_LIGHTDIRECTION;
2335 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2336 permutation |= SHADERPERMUTATION_GLOW;
2337 permutation |= SHADERPERMUTATION_DIFFUSE;
2338 if (specularscale > 0)
2339 permutation |= SHADERPERMUTATION_SPECULAR;
2340 if (r_refdef.fogenabled)
2341 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2342 if (rsurface.texture->colormapping)
2343 permutation |= SHADERPERMUTATION_COLORMAPPING;
2344 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2346 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2347 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2349 if (r_shadow_shadowmap2ddepthbuffer)
2350 permutation |= SHADERPERMUTATION_DEPTHRGB;
2352 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2353 permutation |= SHADERPERMUTATION_REFLECTION;
2354 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2355 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2356 if (rsurface.texture->reflectmasktexture)
2357 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2358 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2360 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2361 if (r_shadow_bouncegriddirectional)
2362 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2364 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2365 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2366 // when using alphatocoverage, we don't need alphakill
2367 if (vid.allowalphatocoverage)
2369 if (r_transparent_alphatocoverage.integer)
2371 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2372 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2375 GL_AlphaToCoverage(false);
2378 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2380 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2382 switch(rsurface.texture->offsetmapping)
2384 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2385 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2386 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2387 case OFFSETMAPPING_OFF: break;
2390 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2391 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2392 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2393 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2394 // ambient model lighting
2395 mode = SHADERMODE_LIGHTDIRECTION;
2396 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2397 permutation |= SHADERPERMUTATION_GLOW;
2398 if (r_refdef.fogenabled)
2399 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2400 if (rsurface.texture->colormapping)
2401 permutation |= SHADERPERMUTATION_COLORMAPPING;
2402 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2404 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2405 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2407 if (r_shadow_shadowmap2ddepthbuffer)
2408 permutation |= SHADERPERMUTATION_DEPTHRGB;
2410 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2411 permutation |= SHADERPERMUTATION_REFLECTION;
2412 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2413 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2414 if (rsurface.texture->reflectmasktexture)
2415 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2416 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2418 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2419 if (r_shadow_bouncegriddirectional)
2420 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2422 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2423 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2424 // when using alphatocoverage, we don't need alphakill
2425 if (vid.allowalphatocoverage)
2427 if (r_transparent_alphatocoverage.integer)
2429 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2430 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2433 GL_AlphaToCoverage(false);
2438 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2440 switch(rsurface.texture->offsetmapping)
2442 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2443 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2444 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2445 case OFFSETMAPPING_OFF: break;
2448 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2449 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2450 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2451 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2453 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2454 permutation |= SHADERPERMUTATION_GLOW;
2455 if (r_refdef.fogenabled)
2456 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2457 if (rsurface.texture->colormapping)
2458 permutation |= SHADERPERMUTATION_COLORMAPPING;
2459 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2461 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2462 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2464 if (r_shadow_shadowmap2ddepthbuffer)
2465 permutation |= SHADERPERMUTATION_DEPTHRGB;
2467 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2468 permutation |= SHADERPERMUTATION_REFLECTION;
2469 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2470 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2471 if (rsurface.texture->reflectmasktexture)
2472 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2473 if (FAKELIGHT_ENABLED)
2475 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2476 mode = SHADERMODE_FAKELIGHT;
2477 permutation |= SHADERPERMUTATION_DIFFUSE;
2478 if (specularscale > 0)
2479 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2481 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2483 // deluxemapping (light direction texture)
2484 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2485 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2487 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2488 permutation |= SHADERPERMUTATION_DIFFUSE;
2489 if (specularscale > 0)
2490 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2492 else if (r_glsl_deluxemapping.integer >= 2)
2494 // fake deluxemapping (uniform light direction in tangentspace)
2495 if (rsurface.uselightmaptexture)
2496 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2498 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2499 permutation |= SHADERPERMUTATION_DIFFUSE;
2500 if (specularscale > 0)
2501 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2503 else if (rsurface.uselightmaptexture)
2505 // ordinary lightmapping (q1bsp, q3bsp)
2506 mode = SHADERMODE_LIGHTMAP;
2510 // ordinary vertex coloring (q3bsp)
2511 mode = SHADERMODE_VERTEXCOLOR;
2513 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2515 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2516 if (r_shadow_bouncegriddirectional)
2517 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2519 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2520 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2521 // when using alphatocoverage, we don't need alphakill
2522 if (vid.allowalphatocoverage)
2524 if (r_transparent_alphatocoverage.integer)
2526 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2527 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2530 GL_AlphaToCoverage(false);
2533 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2534 colormod = dummy_colormod;
2535 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2536 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2537 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2538 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2539 switch(vid.renderpath)
2541 case RENDERPATH_D3D9:
2543 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) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2544 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2545 R_SetupShader_SetPermutationHLSL(mode, permutation);
2546 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2547 if (mode == SHADERMODE_LIGHTSOURCE)
2549 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2550 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2554 if (mode == SHADERMODE_LIGHTDIRECTION)
2556 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2559 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2560 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2561 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2562 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2563 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2565 if (mode == SHADERMODE_LIGHTSOURCE)
2567 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2568 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2569 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2570 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2571 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2573 // additive passes are only darkened by fog, not tinted
2574 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2575 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2579 if (mode == SHADERMODE_FLATCOLOR)
2581 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2583 else if (mode == SHADERMODE_LIGHTDIRECTION)
2585 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]);
2586 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2587 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);
2588 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2589 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2590 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2591 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2595 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2596 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2597 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);
2598 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2599 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2601 // additive passes are only darkened by fog, not tinted
2602 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2603 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2605 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2606 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);
2607 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2608 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2609 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2610 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2611 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2612 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2613 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2614 if (mode == SHADERMODE_WATER)
2615 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2617 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2618 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2619 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2620 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));
2621 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2622 if (rsurface.texture->pantstexture)
2623 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2625 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2626 if (rsurface.texture->shirttexture)
2627 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2629 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2630 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2631 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2632 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2633 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2634 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2635 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2636 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2637 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2638 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2640 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2641 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2642 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2643 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2645 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2646 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2647 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2648 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2649 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2650 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2651 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2652 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2653 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2654 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2655 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2656 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2657 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2658 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2659 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2660 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2661 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2662 if (rsurfacepass == RSURFPASS_BACKGROUND)
2664 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2665 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2666 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2670 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2672 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2673 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2674 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2675 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2677 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2678 if (rsurface.rtlight)
2680 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2681 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2686 case RENDERPATH_D3D10:
2687 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2689 case RENDERPATH_D3D11:
2690 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2692 case RENDERPATH_GL20:
2693 case RENDERPATH_GLES2:
2694 if (!vid.useinterleavedarrays)
2696 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) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2697 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2698 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2699 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2700 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2701 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2702 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2703 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2704 R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2705 R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2706 R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2710 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) | (rsurface.entityskeletaltransform3x4 ? BATCHNEED_VERTEXMESH_SKELETAL : 0) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2711 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2713 // this has to be after RSurf_PrepareVerticesForBatch
2714 if (rsurface.batchskeletaltransform3x4)
2715 permutation |= SHADERPERMUTATION_SKELETAL;
2716 R_SetupShader_SetPermutationGLSL(mode, permutation);
2717 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2718 if (mode == SHADERMODE_LIGHTSOURCE)
2720 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2721 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2722 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2723 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2724 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2725 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);
2727 // additive passes are only darkened by fog, not tinted
2728 if (r_glsl_permutation->loc_FogColor >= 0)
2729 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2730 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);
2734 if (mode == SHADERMODE_FLATCOLOR)
2736 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2738 else if (mode == SHADERMODE_LIGHTDIRECTION)
2740 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]);
2741 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]);
2742 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);
2743 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2744 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2745 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]);
2746 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]);
2750 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]);
2751 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]);
2752 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);
2753 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2754 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2756 // additive passes are only darkened by fog, not tinted
2757 if (r_glsl_permutation->loc_FogColor >= 0)
2759 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2760 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2762 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2764 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);
2765 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]);
2766 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]);
2767 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]);
2768 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]);
2769 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2770 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2771 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);
2772 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]);
2774 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2775 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2776 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2777 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]);
2778 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]);
2780 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2781 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));
2782 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2783 if (r_glsl_permutation->loc_Color_Pants >= 0)
2785 if (rsurface.texture->pantstexture)
2786 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2788 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2790 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2792 if (rsurface.texture->shirttexture)
2793 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2795 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2797 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]);
2798 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2799 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2800 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2801 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2802 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2803 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2804 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2805 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2807 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);
2808 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2809 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]);
2810 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2811 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);}
2812 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2814 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2815 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2816 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2817 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2818 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2819 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2820 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2821 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2822 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2823 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2824 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2825 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2826 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2827 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2828 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);
2829 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2830 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2831 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2832 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2833 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2834 if (rsurfacepass == RSURFPASS_BACKGROUND)
2836 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);
2837 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);
2838 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);
2842 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);
2844 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2845 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2846 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2847 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2849 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture );
2850 if (rsurface.rtlight)
2852 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2853 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2856 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2857 if (r_glsl_permutation->loc_Skeletal_Transform12 >= 0 && rsurface.batchskeletalnumtransforms > 0)
2858 qglUniform4fv(r_glsl_permutation->loc_Skeletal_Transform12, rsurface.batchskeletalnumtransforms*3, rsurface.batchskeletaltransform3x4);
2861 case RENDERPATH_GL11:
2862 case RENDERPATH_GL13:
2863 case RENDERPATH_GLES1:
2865 case RENDERPATH_SOFT:
2866 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) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2867 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2868 R_SetupShader_SetPermutationSoft(mode, permutation);
2869 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2870 if (mode == SHADERMODE_LIGHTSOURCE)
2872 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2873 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2874 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2875 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2876 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2877 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2879 // additive passes are only darkened by fog, not tinted
2880 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2881 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2885 if (mode == SHADERMODE_FLATCOLOR)
2887 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2889 else if (mode == SHADERMODE_LIGHTDIRECTION)
2891 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]);
2892 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2893 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);
2894 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2895 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2896 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]);
2897 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2901 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2902 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2903 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);
2904 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2905 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2907 // additive passes are only darkened by fog, not tinted
2908 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2909 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2911 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2912 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);
2913 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]);
2914 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]);
2915 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]);
2916 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]);
2917 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2918 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2919 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2920 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2922 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2923 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2924 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2925 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2926 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]);
2928 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2929 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));
2930 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2931 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2933 if (rsurface.texture->pantstexture)
2934 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2936 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2938 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2940 if (rsurface.texture->shirttexture)
2941 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2943 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2945 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2946 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2947 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2948 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2949 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2950 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2951 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2952 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2953 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2955 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2956 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2957 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2958 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2960 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2961 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2962 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2963 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2964 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2965 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2966 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2967 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2968 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2969 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2970 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2971 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2972 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2973 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2974 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2975 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2976 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2977 if (rsurfacepass == RSURFPASS_BACKGROUND)
2979 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2980 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2981 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2985 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2987 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2988 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2989 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2990 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2992 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2993 if (rsurface.rtlight)
2995 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2996 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3003 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3005 // select a permutation of the lighting shader appropriate to this
3006 // combination of texture, entity, light source, and fogging, only use the
3007 // minimum features necessary to avoid wasting rendering time in the
3008 // fragment shader on features that are not being used
3009 unsigned int permutation = 0;
3010 unsigned int mode = 0;
3011 const float *lightcolorbase = rtlight->currentcolor;
3012 float ambientscale = rtlight->ambientscale;
3013 float diffusescale = rtlight->diffusescale;
3014 float specularscale = rtlight->specularscale;
3015 // this is the location of the light in view space
3016 vec3_t viewlightorigin;
3017 // this transforms from view space (camera) to light space (cubemap)
3018 matrix4x4_t viewtolight;
3019 matrix4x4_t lighttoview;
3020 float viewtolight16f[16];
3022 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3023 if (rtlight->currentcubemap != r_texture_whitecube)
3024 permutation |= SHADERPERMUTATION_CUBEFILTER;
3025 if (diffusescale > 0)
3026 permutation |= SHADERPERMUTATION_DIFFUSE;
3027 if (specularscale > 0 && r_shadow_gloss.integer > 0)
3028 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3029 if (r_shadow_usingshadowmap2d)
3031 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3032 if (r_shadow_shadowmapvsdct)
3033 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3035 if (r_shadow_shadowmap2ddepthbuffer)
3036 permutation |= SHADERPERMUTATION_DEPTHRGB;
3038 if (vid.allowalphatocoverage)
3039 GL_AlphaToCoverage(false);
3040 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3041 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3042 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3043 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3044 switch(vid.renderpath)
3046 case RENDERPATH_D3D9:
3048 R_SetupShader_SetPermutationHLSL(mode, permutation);
3049 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3050 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3051 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3052 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3053 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3054 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3055 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3056 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);
3057 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3058 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3060 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3061 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3062 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3063 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2ddepthtexture );
3064 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3067 case RENDERPATH_D3D10:
3068 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3070 case RENDERPATH_D3D11:
3071 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3073 case RENDERPATH_GL20:
3074 case RENDERPATH_GLES2:
3075 R_SetupShader_SetPermutationGLSL(mode, permutation);
3076 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3077 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
3078 if (r_glsl_permutation->loc_DeferredColor_Ambient >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3079 if (r_glsl_permutation->loc_DeferredColor_Diffuse >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3080 if (r_glsl_permutation->loc_DeferredColor_Specular >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3081 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]);
3082 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]);
3083 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);
3084 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]);
3085 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
3087 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
3088 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
3089 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
3090 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2ddepthtexture );
3091 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
3093 case RENDERPATH_GL11:
3094 case RENDERPATH_GL13:
3095 case RENDERPATH_GLES1:
3097 case RENDERPATH_SOFT:
3098 R_SetupShader_SetPermutationGLSL(mode, permutation);
3099 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3100 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
3101 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3102 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3103 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3104 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3105 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]);
3106 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);
3107 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3108 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3110 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3111 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3112 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3113 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2ddepthtexture );
3114 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3119 #define SKINFRAME_HASH 1024
3123 int loadsequence; // incremented each level change
3124 memexpandablearray_t array;
3125 skinframe_t *hash[SKINFRAME_HASH];
3128 r_skinframe_t r_skinframe;
3130 void R_SkinFrame_PrepareForPurge(void)
3132 r_skinframe.loadsequence++;
3133 // wrap it without hitting zero
3134 if (r_skinframe.loadsequence >= 200)
3135 r_skinframe.loadsequence = 1;
3138 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3142 // mark the skinframe as used for the purging code
3143 skinframe->loadsequence = r_skinframe.loadsequence;
3146 void R_SkinFrame_Purge(void)
3150 for (i = 0;i < SKINFRAME_HASH;i++)
3152 for (s = r_skinframe.hash[i];s;s = s->next)
3154 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3156 if (s->merged == s->base)
3158 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3159 R_PurgeTexture(s->stain );s->stain = NULL;
3160 R_PurgeTexture(s->merged);s->merged = NULL;
3161 R_PurgeTexture(s->base );s->base = NULL;
3162 R_PurgeTexture(s->pants );s->pants = NULL;
3163 R_PurgeTexture(s->shirt );s->shirt = NULL;
3164 R_PurgeTexture(s->nmap );s->nmap = NULL;
3165 R_PurgeTexture(s->gloss );s->gloss = NULL;
3166 R_PurgeTexture(s->glow );s->glow = NULL;
3167 R_PurgeTexture(s->fog );s->fog = NULL;
3168 R_PurgeTexture(s->reflect);s->reflect = NULL;
3169 s->loadsequence = 0;
3175 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3177 char basename[MAX_QPATH];
3179 Image_StripImageExtension(name, basename, sizeof(basename));
3181 if( last == NULL ) {
3183 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3184 item = r_skinframe.hash[hashindex];
3189 // linearly search through the hash bucket
3190 for( ; item ; item = item->next ) {
3191 if( !strcmp( item->basename, basename ) ) {
3198 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3202 char basename[MAX_QPATH];
3204 Image_StripImageExtension(name, basename, sizeof(basename));
3206 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3207 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3208 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3212 rtexture_t *dyntexture;
3213 // check whether its a dynamic texture
3214 dyntexture = CL_GetDynTexture( basename );
3215 if (!add && !dyntexture)
3217 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3218 memset(item, 0, sizeof(*item));
3219 strlcpy(item->basename, basename, sizeof(item->basename));
3220 item->base = dyntexture; // either NULL or dyntexture handle
3221 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3222 item->comparewidth = comparewidth;
3223 item->compareheight = compareheight;
3224 item->comparecrc = comparecrc;
3225 item->next = r_skinframe.hash[hashindex];
3226 r_skinframe.hash[hashindex] = item;
3228 else if (textureflags & TEXF_FORCE_RELOAD)
3230 rtexture_t *dyntexture;
3231 // check whether its a dynamic texture
3232 dyntexture = CL_GetDynTexture( basename );
3233 if (!add && !dyntexture)
3235 if (item->merged == item->base)
3236 item->merged = NULL;
3237 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3238 R_PurgeTexture(item->stain );item->stain = NULL;
3239 R_PurgeTexture(item->merged);item->merged = NULL;
3240 R_PurgeTexture(item->base );item->base = NULL;
3241 R_PurgeTexture(item->pants );item->pants = NULL;
3242 R_PurgeTexture(item->shirt );item->shirt = NULL;
3243 R_PurgeTexture(item->nmap );item->nmap = NULL;
3244 R_PurgeTexture(item->gloss );item->gloss = NULL;
3245 R_PurgeTexture(item->glow );item->glow = NULL;
3246 R_PurgeTexture(item->fog );item->fog = NULL;
3247 R_PurgeTexture(item->reflect);item->reflect = NULL;
3248 item->loadsequence = 0;
3250 else if( item->base == NULL )
3252 rtexture_t *dyntexture;
3253 // check whether its a dynamic texture
3254 // 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]
3255 dyntexture = CL_GetDynTexture( basename );
3256 item->base = dyntexture; // either NULL or dyntexture handle
3259 R_SkinFrame_MarkUsed(item);
3263 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3265 unsigned long long avgcolor[5], wsum; \
3273 for(pix = 0; pix < cnt; ++pix) \
3276 for(comp = 0; comp < 3; ++comp) \
3278 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3281 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3283 for(comp = 0; comp < 3; ++comp) \
3284 avgcolor[comp] += getpixel * w; \
3287 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3288 avgcolor[4] += getpixel; \
3290 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3292 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3293 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3294 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3295 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3298 extern cvar_t gl_picmip;
3299 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3302 unsigned char *pixels;
3303 unsigned char *bumppixels;
3304 unsigned char *basepixels = NULL;
3305 int basepixels_width = 0;
3306 int basepixels_height = 0;
3307 skinframe_t *skinframe;
3308 rtexture_t *ddsbase = NULL;
3309 qboolean ddshasalpha = false;
3310 float ddsavgcolor[4];
3311 char basename[MAX_QPATH];
3312 int miplevel = R_PicmipForFlags(textureflags);
3313 int savemiplevel = miplevel;
3317 if (cls.state == ca_dedicated)
3320 // return an existing skinframe if already loaded
3321 // if loading of the first image fails, don't make a new skinframe as it
3322 // would cause all future lookups of this to be missing
3323 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3324 if (skinframe && skinframe->base)
3327 Image_StripImageExtension(name, basename, sizeof(basename));
3329 // check for DDS texture file first
3330 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3332 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3333 if (basepixels == NULL)
3337 // FIXME handle miplevel
3339 if (developer_loading.integer)
3340 Con_Printf("loading skin \"%s\"\n", name);
3342 // we've got some pixels to store, so really allocate this new texture now
3344 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3345 textureflags &= ~TEXF_FORCE_RELOAD;
3346 skinframe->stain = NULL;
3347 skinframe->merged = NULL;
3348 skinframe->base = NULL;
3349 skinframe->pants = NULL;
3350 skinframe->shirt = NULL;
3351 skinframe->nmap = NULL;
3352 skinframe->gloss = NULL;
3353 skinframe->glow = NULL;
3354 skinframe->fog = NULL;
3355 skinframe->reflect = NULL;
3356 skinframe->hasalpha = false;
3360 skinframe->base = ddsbase;
3361 skinframe->hasalpha = ddshasalpha;
3362 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3363 if (r_loadfog && skinframe->hasalpha)
3364 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), false, textureflags | TEXF_ALPHA, NULL, NULL, miplevel, true);
3365 //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]);
3369 basepixels_width = image_width;
3370 basepixels_height = image_height;
3371 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);
3372 if (textureflags & TEXF_ALPHA)
3374 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3376 if (basepixels[j] < 255)
3378 skinframe->hasalpha = true;
3382 if (r_loadfog && skinframe->hasalpha)
3384 // has transparent pixels
3385 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3386 for (j = 0;j < image_width * image_height * 4;j += 4)
3391 pixels[j+3] = basepixels[j+3];
3393 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);
3397 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3399 //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]);
3400 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3401 R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3402 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3403 R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3409 mymiplevel = savemiplevel;
3410 if (r_loadnormalmap)
3411 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, true);
3412 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3414 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3415 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3416 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3417 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3420 // _norm is the name used by tenebrae and has been adopted as standard
3421 if (r_loadnormalmap && skinframe->nmap == NULL)
3423 mymiplevel = savemiplevel;
3424 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3426 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);
3430 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3432 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3433 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3434 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);
3436 Mem_Free(bumppixels);
3438 else if (r_shadow_bumpscale_basetexture.value > 0)
3440 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3441 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3442 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);
3446 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3447 R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3451 // _luma is supported only for tenebrae compatibility
3452 // _glow is the preferred name
3453 mymiplevel = savemiplevel;
3454 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))))
3456 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);
3458 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3459 R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3461 Mem_Free(pixels);pixels = NULL;
3464 mymiplevel = savemiplevel;
3465 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3467 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);
3469 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3470 R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3476 mymiplevel = savemiplevel;
3477 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3479 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);
3481 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3482 R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3488 mymiplevel = savemiplevel;
3489 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3491 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);
3493 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3494 R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3500 mymiplevel = savemiplevel;
3501 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3503 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);
3505 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3506 R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3513 Mem_Free(basepixels);
3518 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3519 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3522 unsigned char *temp1, *temp2;
3523 skinframe_t *skinframe;
3526 if (cls.state == ca_dedicated)
3529 // if already loaded just return it, otherwise make a new skinframe
3530 skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3531 if (skinframe->base)
3533 textureflags &= ~TEXF_FORCE_RELOAD;
3535 skinframe->stain = NULL;
3536 skinframe->merged = NULL;
3537 skinframe->base = NULL;
3538 skinframe->pants = NULL;
3539 skinframe->shirt = NULL;
3540 skinframe->nmap = NULL;
3541 skinframe->gloss = NULL;
3542 skinframe->glow = NULL;
3543 skinframe->fog = NULL;
3544 skinframe->reflect = NULL;
3545 skinframe->hasalpha = false;
3547 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3551 if (developer_loading.integer)
3552 Con_Printf("loading 32bit skin \"%s\"\n", name);
3554 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3556 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3557 temp2 = temp1 + width * height * 4;
3558 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3559 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);
3562 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3563 if (textureflags & TEXF_ALPHA)
3565 for (i = 3;i < width * height * 4;i += 4)
3567 if (skindata[i] < 255)
3569 skinframe->hasalpha = true;
3573 if (r_loadfog && skinframe->hasalpha)
3575 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3576 memcpy(fogpixels, skindata, width * height * 4);
3577 for (i = 0;i < width * height * 4;i += 4)
3578 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3579 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3580 Mem_Free(fogpixels);
3584 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3585 //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]);
3590 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3594 skinframe_t *skinframe;
3596 if (cls.state == ca_dedicated)
3599 // if already loaded just return it, otherwise make a new skinframe
3600 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3601 if (skinframe->base)
3603 //textureflags &= ~TEXF_FORCE_RELOAD;
3605 skinframe->stain = NULL;
3606 skinframe->merged = NULL;
3607 skinframe->base = NULL;
3608 skinframe->pants = NULL;
3609 skinframe->shirt = NULL;
3610 skinframe->nmap = NULL;
3611 skinframe->gloss = NULL;
3612 skinframe->glow = NULL;
3613 skinframe->fog = NULL;
3614 skinframe->reflect = NULL;
3615 skinframe->hasalpha = false;
3617 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3621 if (developer_loading.integer)
3622 Con_Printf("loading quake skin \"%s\"\n", name);
3624 // 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)
3625 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3626 memcpy(skinframe->qpixels, skindata, width*height);
3627 skinframe->qwidth = width;
3628 skinframe->qheight = height;
3631 for (i = 0;i < width * height;i++)
3632 featuresmask |= palette_featureflags[skindata[i]];
3634 skinframe->hasalpha = false;
3635 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3636 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3637 skinframe->qgeneratemerged = true;
3638 skinframe->qgeneratebase = skinframe->qhascolormapping;
3639 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3641 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3642 //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]);
3647 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3651 unsigned char *skindata;
3654 if (!skinframe->qpixels)
3657 if (!skinframe->qhascolormapping)
3658 colormapped = false;
3662 if (!skinframe->qgeneratebase)
3667 if (!skinframe->qgeneratemerged)
3671 width = skinframe->qwidth;
3672 height = skinframe->qheight;
3673 skindata = skinframe->qpixels;
3675 if (skinframe->qgeneratenmap)
3677 unsigned char *temp1, *temp2;
3678 skinframe->qgeneratenmap = false;
3679 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3680 temp2 = temp1 + width * height * 4;
3681 // use either a custom palette or the quake palette
3682 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3683 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3684 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);
3688 if (skinframe->qgenerateglow)
3690 skinframe->qgenerateglow = false;
3691 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
3696 skinframe->qgeneratebase = false;
3697 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);
3698 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);
3699 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);
3703 skinframe->qgeneratemerged = false;
3704 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);
3707 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3709 Mem_Free(skinframe->qpixels);
3710 skinframe->qpixels = NULL;
3714 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)
3717 skinframe_t *skinframe;
3720 if (cls.state == ca_dedicated)
3723 // if already loaded just return it, otherwise make a new skinframe
3724 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3725 if (skinframe->base)
3727 textureflags &= ~TEXF_FORCE_RELOAD;
3729 skinframe->stain = NULL;
3730 skinframe->merged = NULL;
3731 skinframe->base = NULL;
3732 skinframe->pants = NULL;
3733 skinframe->shirt = NULL;
3734 skinframe->nmap = NULL;
3735 skinframe->gloss = NULL;
3736 skinframe->glow = NULL;
3737 skinframe->fog = NULL;
3738 skinframe->reflect = NULL;
3739 skinframe->hasalpha = false;
3741 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3745 if (developer_loading.integer)
3746 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3748 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3749 if (textureflags & TEXF_ALPHA)
3751 for (i = 0;i < width * height;i++)
3753 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3755 skinframe->hasalpha = true;
3759 if (r_loadfog && skinframe->hasalpha)
3760 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3763 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3764 //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]);
3769 skinframe_t *R_SkinFrame_LoadMissing(void)
3771 skinframe_t *skinframe;
3773 if (cls.state == ca_dedicated)
3776 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3777 skinframe->stain = NULL;
3778 skinframe->merged = NULL;
3779 skinframe->base = NULL;
3780 skinframe->pants = NULL;
3781 skinframe->shirt = NULL;
3782 skinframe->nmap = NULL;
3783 skinframe->gloss = NULL;
3784 skinframe->glow = NULL;
3785 skinframe->fog = NULL;
3786 skinframe->reflect = NULL;
3787 skinframe->hasalpha = false;
3789 skinframe->avgcolor[0] = rand() / RAND_MAX;
3790 skinframe->avgcolor[1] = rand() / RAND_MAX;
3791 skinframe->avgcolor[2] = rand() / RAND_MAX;
3792 skinframe->avgcolor[3] = 1;
3797 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3798 typedef struct suffixinfo_s
3801 qboolean flipx, flipy, flipdiagonal;
3804 static suffixinfo_t suffix[3][6] =
3807 {"px", false, false, false},
3808 {"nx", false, false, false},
3809 {"py", false, false, false},
3810 {"ny", false, false, false},
3811 {"pz", false, false, false},
3812 {"nz", false, false, false}
3815 {"posx", false, false, false},
3816 {"negx", false, false, false},
3817 {"posy", false, false, false},
3818 {"negy", false, false, false},
3819 {"posz", false, false, false},
3820 {"negz", false, false, false}
3823 {"rt", true, false, true},
3824 {"lf", false, true, true},
3825 {"ft", true, true, false},
3826 {"bk", false, false, false},
3827 {"up", true, false, true},
3828 {"dn", true, false, true}
3832 static int componentorder[4] = {0, 1, 2, 3};
3834 static rtexture_t *R_LoadCubemap(const char *basename)
3836 int i, j, cubemapsize;
3837 unsigned char *cubemappixels, *image_buffer;
3838 rtexture_t *cubemaptexture;
3840 // must start 0 so the first loadimagepixels has no requested width/height
3842 cubemappixels = NULL;
3843 cubemaptexture = NULL;
3844 // keep trying different suffix groups (posx, px, rt) until one loads
3845 for (j = 0;j < 3 && !cubemappixels;j++)
3847 // load the 6 images in the suffix group
3848 for (i = 0;i < 6;i++)
3850 // generate an image name based on the base and and suffix
3851 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3853 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3855 // an image loaded, make sure width and height are equal
3856 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3858 // if this is the first image to load successfully, allocate the cubemap memory
3859 if (!cubemappixels && image_width >= 1)
3861 cubemapsize = image_width;
3862 // note this clears to black, so unavailable sides are black
3863 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3865 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3867 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);
3870 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3872 Mem_Free(image_buffer);
3876 // if a cubemap loaded, upload it
3879 if (developer_loading.integer)
3880 Con_Printf("loading cubemap \"%s\"\n", basename);
3882 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);
3883 Mem_Free(cubemappixels);
3887 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3888 if (developer_loading.integer)
3890 Con_Printf("(tried tried images ");
3891 for (j = 0;j < 3;j++)
3892 for (i = 0;i < 6;i++)
3893 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3894 Con_Print(" and was unable to find any of them).\n");
3897 return cubemaptexture;
3900 rtexture_t *R_GetCubemap(const char *basename)
3903 for (i = 0;i < r_texture_numcubemaps;i++)
3904 if (r_texture_cubemaps[i] != NULL)
3905 if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3906 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3907 if (i >= MAX_CUBEMAPS || !r_main_mempool)
3908 return r_texture_whitecube;
3909 r_texture_numcubemaps++;
3910 r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3911 strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3912 r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3913 return r_texture_cubemaps[i]->texture;
3916 static void R_Main_FreeViewCache(void)
3918 if (r_refdef.viewcache.entityvisible)
3919 Mem_Free(r_refdef.viewcache.entityvisible);
3920 if (r_refdef.viewcache.world_pvsbits)
3921 Mem_Free(r_refdef.viewcache.world_pvsbits);
3922 if (r_refdef.viewcache.world_leafvisible)
3923 Mem_Free(r_refdef.viewcache.world_leafvisible);
3924 if (r_refdef.viewcache.world_surfacevisible)
3925 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3926 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3929 static void R_Main_ResizeViewCache(void)
3931 int numentities = r_refdef.scene.numentities;
3932 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3933 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3934 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3935 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3936 if (r_refdef.viewcache.maxentities < numentities)
3938 r_refdef.viewcache.maxentities = numentities;
3939 if (r_refdef.viewcache.entityvisible)
3940 Mem_Free(r_refdef.viewcache.entityvisible);
3941 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3943 if (r_refdef.viewcache.world_numclusters != numclusters)
3945 r_refdef.viewcache.world_numclusters = numclusters;
3946 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3947 if (r_refdef.viewcache.world_pvsbits)
3948 Mem_Free(r_refdef.viewcache.world_pvsbits);
3949 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3951 if (r_refdef.viewcache.world_numleafs != numleafs)
3953 r_refdef.viewcache.world_numleafs = numleafs;
3954 if (r_refdef.viewcache.world_leafvisible)
3955 Mem_Free(r_refdef.viewcache.world_leafvisible);
3956 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3958 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3960 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3961 if (r_refdef.viewcache.world_surfacevisible)
3962 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3963 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3967 extern rtexture_t *loadingscreentexture;
3968 static void gl_main_start(void)
3970 loadingscreentexture = NULL;
3971 r_texture_blanknormalmap = NULL;
3972 r_texture_white = NULL;
3973 r_texture_grey128 = NULL;
3974 r_texture_black = NULL;
3975 r_texture_whitecube = NULL;
3976 r_texture_normalizationcube = NULL;
3977 r_texture_fogattenuation = NULL;
3978 r_texture_fogheighttexture = NULL;
3979 r_texture_gammaramps = NULL;
3980 r_texture_numcubemaps = 0;
3982 r_loaddds = r_texture_dds_load.integer != 0;
3983 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3985 switch(vid.renderpath)
3987 case RENDERPATH_GL20:
3988 case RENDERPATH_D3D9:
3989 case RENDERPATH_D3D10:
3990 case RENDERPATH_D3D11:
3991 case RENDERPATH_SOFT:
3992 case RENDERPATH_GLES2:
3993 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3994 Cvar_SetValueQuick(&gl_combine, 1);
3995 Cvar_SetValueQuick(&r_glsl, 1);
3996 r_loadnormalmap = true;
4000 case RENDERPATH_GL13:
4001 case RENDERPATH_GLES1:
4002 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4003 Cvar_SetValueQuick(&gl_combine, 1);
4004 Cvar_SetValueQuick(&r_glsl, 0);
4005 r_loadnormalmap = false;
4006 r_loadgloss = false;
4009 case RENDERPATH_GL11:
4010 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4011 Cvar_SetValueQuick(&gl_combine, 0);
4012 Cvar_SetValueQuick(&r_glsl, 0);
4013 r_loadnormalmap = false;
4014 r_loadgloss = false;
4020 R_FrameData_Reset();
4024 memset(r_queries, 0, sizeof(r_queries));
4026 r_qwskincache = NULL;
4027 r_qwskincache_size = 0;
4029 // due to caching of texture_t references, the collision cache must be reset
4030 Collision_Cache_Reset(true);
4032 // set up r_skinframe loading system for textures
4033 memset(&r_skinframe, 0, sizeof(r_skinframe));
4034 r_skinframe.loadsequence = 1;
4035 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4037 r_main_texturepool = R_AllocTexturePool();
4038 R_BuildBlankTextures();
4040 if (vid.support.arb_texture_cube_map)
4043 R_BuildNormalizationCube();
4045 r_texture_fogattenuation = NULL;
4046 r_texture_fogheighttexture = NULL;
4047 r_texture_gammaramps = NULL;
4048 //r_texture_fogintensity = NULL;
4049 memset(&r_fb, 0, sizeof(r_fb));
4050 r_glsl_permutation = NULL;
4051 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4052 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4053 glslshaderstring = NULL;
4055 r_hlsl_permutation = NULL;
4056 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4057 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4059 hlslshaderstring = NULL;
4060 memset(&r_svbsp, 0, sizeof (r_svbsp));
4062 memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4063 r_texture_numcubemaps = 0;
4065 r_refdef.fogmasktable_density = 0;
4068 static void gl_main_shutdown(void)
4071 R_FrameData_Reset();
4073 R_Main_FreeViewCache();
4075 switch(vid.renderpath)
4077 case RENDERPATH_GL11:
4078 case RENDERPATH_GL13:
4079 case RENDERPATH_GL20:
4080 case RENDERPATH_GLES1:
4081 case RENDERPATH_GLES2:
4082 #ifdef GL_SAMPLES_PASSED_ARB
4084 qglDeleteQueriesARB(r_maxqueries, r_queries);
4087 case RENDERPATH_D3D9:
4088 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4090 case RENDERPATH_D3D10:
4091 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4093 case RENDERPATH_D3D11:
4094 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4096 case RENDERPATH_SOFT:
4102 memset(r_queries, 0, sizeof(r_queries));
4104 r_qwskincache = NULL;
4105 r_qwskincache_size = 0;
4107 // clear out the r_skinframe state
4108 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4109 memset(&r_skinframe, 0, sizeof(r_skinframe));
4112 Mem_Free(r_svbsp.nodes);
4113 memset(&r_svbsp, 0, sizeof (r_svbsp));
4114 R_FreeTexturePool(&r_main_texturepool);
4115 loadingscreentexture = NULL;
4116 r_texture_blanknormalmap = NULL;
4117 r_texture_white = NULL;
4118 r_texture_grey128 = NULL;
4119 r_texture_black = NULL;
4120 r_texture_whitecube = NULL;
4121 r_texture_normalizationcube = NULL;
4122 r_texture_fogattenuation = NULL;
4123 r_texture_fogheighttexture = NULL;
4124 r_texture_gammaramps = NULL;
4125 r_texture_numcubemaps = 0;
4126 //r_texture_fogintensity = NULL;
4127 memset(&r_fb, 0, sizeof(r_fb));
4130 r_glsl_permutation = NULL;
4131 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4132 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4133 glslshaderstring = NULL;
4135 r_hlsl_permutation = NULL;
4136 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4137 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4139 hlslshaderstring = NULL;
4142 static void gl_main_newmap(void)
4144 // FIXME: move this code to client
4145 char *entities, entname[MAX_QPATH];
4147 Mem_Free(r_qwskincache);
4148 r_qwskincache = NULL;
4149 r_qwskincache_size = 0;
4152 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4153 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4155 CL_ParseEntityLump(entities);
4159 if (cl.worldmodel->brush.entities)
4160 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4162 R_Main_FreeViewCache();
4164 R_FrameData_Reset();
4167 void GL_Main_Init(void)
4169 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4171 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4172 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4173 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4174 if (gamemode == GAME_NEHAHRA)
4176 Cvar_RegisterVariable (&gl_fogenable);
4177 Cvar_RegisterVariable (&gl_fogdensity);
4178 Cvar_RegisterVariable (&gl_fogred);
4179 Cvar_RegisterVariable (&gl_foggreen);
4180 Cvar_RegisterVariable (&gl_fogblue);
4181 Cvar_RegisterVariable (&gl_fogstart);
4182 Cvar_RegisterVariable (&gl_fogend);
4183 Cvar_RegisterVariable (&gl_skyclip);
4185 Cvar_RegisterVariable(&r_motionblur);
4186 Cvar_RegisterVariable(&r_damageblur);
4187 Cvar_RegisterVariable(&r_motionblur_averaging);
4188 Cvar_RegisterVariable(&r_motionblur_randomize);
4189 Cvar_RegisterVariable(&r_motionblur_minblur);
4190 Cvar_RegisterVariable(&r_motionblur_maxblur);
4191 Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4192 Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4193 Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4194 Cvar_RegisterVariable(&r_motionblur_mousefactor);
4195 Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4196 Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4197 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4198 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4199 Cvar_RegisterVariable(&r_equalize_entities_by);
4200 Cvar_RegisterVariable(&r_equalize_entities_to);
4201 Cvar_RegisterVariable(&r_depthfirst);
4202 Cvar_RegisterVariable(&r_useinfinitefarclip);
4203 Cvar_RegisterVariable(&r_farclip_base);
4204 Cvar_RegisterVariable(&r_farclip_world);
4205 Cvar_RegisterVariable(&r_nearclip);
4206 Cvar_RegisterVariable(&r_deformvertexes);
4207 Cvar_RegisterVariable(&r_transparent);
4208 Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4209 Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4210 Cvar_RegisterVariable(&r_transparent_useplanardistance);
4211 Cvar_RegisterVariable(&r_showoverdraw);
4212 Cvar_RegisterVariable(&r_showbboxes);
4213 Cvar_RegisterVariable(&r_showsurfaces);
4214 Cvar_RegisterVariable(&r_showtris);
4215 Cvar_RegisterVariable(&r_shownormals);
4216 Cvar_RegisterVariable(&r_showlighting);
4217 Cvar_RegisterVariable(&r_showshadowvolumes);
4218 Cvar_RegisterVariable(&r_showcollisionbrushes);
4219 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4220 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4221 Cvar_RegisterVariable(&r_showdisabledepthtest);
4222 Cvar_RegisterVariable(&r_drawportals);
4223 Cvar_RegisterVariable(&r_drawentities);
4224 Cvar_RegisterVariable(&r_draw2d);
4225 Cvar_RegisterVariable(&r_drawworld);
4226 Cvar_RegisterVariable(&r_cullentities_trace);
4227 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4228 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4229 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4230 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4231 Cvar_RegisterVariable(&r_sortentities);
4232 Cvar_RegisterVariable(&r_drawviewmodel);
4233 Cvar_RegisterVariable(&r_drawexteriormodel);
4234 Cvar_RegisterVariable(&r_speeds);
4235 Cvar_RegisterVariable(&r_fullbrights);
4236 Cvar_RegisterVariable(&r_wateralpha);
4237 Cvar_RegisterVariable(&r_dynamic);
4238 Cvar_RegisterVariable(&r_fakelight);
4239 Cvar_RegisterVariable(&r_fakelight_intensity);
4240 Cvar_RegisterVariable(&r_fullbright);
4241 Cvar_RegisterVariable(&r_shadows);
4242 Cvar_RegisterVariable(&r_shadows_darken);
4243 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4244 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4245 Cvar_RegisterVariable(&r_shadows_throwdistance);
4246 Cvar_RegisterVariable(&r_shadows_throwdirection);
4247 Cvar_RegisterVariable(&r_shadows_focus);
4248 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4249 Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4250 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4251 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4252 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4253 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4254 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4255 Cvar_RegisterVariable(&r_fog_exp2);
4256 Cvar_RegisterVariable(&r_fog_clear);
4257 Cvar_RegisterVariable(&r_drawfog);
4258 Cvar_RegisterVariable(&r_transparentdepthmasking);
4259 Cvar_RegisterVariable(&r_transparent_sortmindist);
4260 Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4261 Cvar_RegisterVariable(&r_transparent_sortarraysize);
4262 Cvar_RegisterVariable(&r_texture_dds_load);
4263 Cvar_RegisterVariable(&r_texture_dds_save);
4264 Cvar_RegisterVariable(&r_textureunits);
4265 Cvar_RegisterVariable(&gl_combine);
4266 Cvar_RegisterVariable(&r_usedepthtextures);
4267 Cvar_RegisterVariable(&r_viewfbo);
4268 Cvar_RegisterVariable(&r_viewscale);
4269 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4270 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4271 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4272 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4273 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4274 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4275 Cvar_RegisterVariable(&r_glsl);
4276 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4277 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4278 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4279 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4280 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4281 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4282 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4283 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4284 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4285 Cvar_RegisterVariable(&r_glsl_postprocess);
4286 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4287 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4288 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4289 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4290 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4291 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4292 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4293 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4294 Cvar_RegisterVariable(&r_celshading);
4295 Cvar_RegisterVariable(&r_celoutlines);
4297 Cvar_RegisterVariable(&r_water);
4298 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4299 Cvar_RegisterVariable(&r_water_clippingplanebias);
4300 Cvar_RegisterVariable(&r_water_refractdistort);
4301 Cvar_RegisterVariable(&r_water_reflectdistort);
4302 Cvar_RegisterVariable(&r_water_scissormode);
4303 Cvar_RegisterVariable(&r_water_lowquality);
4304 Cvar_RegisterVariable(&r_water_hideplayer);
4305 Cvar_RegisterVariable(&r_water_fbo);
4307 Cvar_RegisterVariable(&r_lerpsprites);
4308 Cvar_RegisterVariable(&r_lerpmodels);
4309 Cvar_RegisterVariable(&r_lerplightstyles);
4310 Cvar_RegisterVariable(&r_waterscroll);
4311 Cvar_RegisterVariable(&r_bloom);
4312 Cvar_RegisterVariable(&r_bloom_colorscale);
4313 Cvar_RegisterVariable(&r_bloom_brighten);
4314 Cvar_RegisterVariable(&r_bloom_blur);
4315 Cvar_RegisterVariable(&r_bloom_resolution);
4316 Cvar_RegisterVariable(&r_bloom_colorexponent);
4317 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4318 Cvar_RegisterVariable(&r_bloom_scenebrightness);
4319 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4320 Cvar_RegisterVariable(&r_hdr_glowintensity);
4321 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4322 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4323 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4324 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4325 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4326 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4327 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4328 Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4329 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4330 Cvar_RegisterVariable(&developer_texturelogging);
4331 Cvar_RegisterVariable(&gl_lightmaps);
4332 Cvar_RegisterVariable(&r_test);
4333 Cvar_RegisterVariable(&r_batch_multidraw);
4334 Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4335 Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4336 Cvar_RegisterVariable(&r_glsl_skeletal);
4337 Cvar_RegisterVariable(&r_glsl_saturation);
4338 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4339 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4340 Cvar_RegisterVariable(&r_framedatasize);
4341 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4342 Cvar_SetValue("r_fullbrights", 0);
4343 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4346 void Render_Init(void)
4359 R_LightningBeams_Init();
4369 extern char *ENGINE_EXTENSIONS;
4372 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4373 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4374 gl_version = (const char *)qglGetString(GL_VERSION);
4375 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4379 if (!gl_platformextensions)
4380 gl_platformextensions = "";
4382 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4383 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4384 Con_Printf("GL_VERSION: %s\n", gl_version);
4385 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4386 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4388 VID_CheckExtensions();
4390 // LordHavoc: report supported extensions
4391 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4393 // clear to black (loading plaque will be seen over this)
4394 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4398 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4402 if (r_trippy.integer)
4404 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4406 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4409 p = r_refdef.view.frustum + i;
4414 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4418 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4422 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4426 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4430 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4434 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4438 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4442 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4450 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4454 if (r_trippy.integer)
4456 for (i = 0;i < numplanes;i++)
4463 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4467 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4471 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4475 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4479 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4483 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4487 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4491 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4499 //==================================================================================
4501 // LordHavoc: this stores temporary data used within the same frame
4503 typedef struct r_framedata_mem_s
4505 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4506 size_t size; // how much usable space
4507 size_t current; // how much space in use
4508 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4509 size_t wantedsize; // how much space was allocated
4510 unsigned char *data; // start of real data (16byte aligned)
4514 static r_framedata_mem_t *r_framedata_mem;
4516 void R_FrameData_Reset(void)
4518 while (r_framedata_mem)
4520 r_framedata_mem_t *next = r_framedata_mem->purge;
4521 Mem_Free(r_framedata_mem);
4522 r_framedata_mem = next;
4526 static void R_FrameData_Resize(void)
4529 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4530 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4531 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4533 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4534 newmem->wantedsize = wantedsize;
4535 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4536 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4537 newmem->current = 0;
4539 newmem->purge = r_framedata_mem;
4540 r_framedata_mem = newmem;
4544 void R_FrameData_NewFrame(void)
4546 R_FrameData_Resize();
4547 if (!r_framedata_mem)
4549 // if we ran out of space on the last frame, free the old memory now
4550 while (r_framedata_mem->purge)
4552 // repeatedly remove the second item in the list, leaving only head
4553 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4554 Mem_Free(r_framedata_mem->purge);
4555 r_framedata_mem->purge = next;
4557 // reset the current mem pointer
4558 r_framedata_mem->current = 0;
4559 r_framedata_mem->mark = 0;
4562 void *R_FrameData_Alloc(size_t size)
4566 // align to 16 byte boundary - the data pointer is already aligned, so we
4567 // only need to ensure the size of every allocation is also aligned
4568 size = (size + 15) & ~15;
4570 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4572 // emergency - we ran out of space, allocate more memory
4573 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4574 R_FrameData_Resize();
4577 data = r_framedata_mem->data + r_framedata_mem->current;
4578 r_framedata_mem->current += size;
4580 // count the usage for stats
4581 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4582 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4584 return (void *)data;
4587 void *R_FrameData_Store(size_t size, void *data)
4589 void *d = R_FrameData_Alloc(size);
4591 memcpy(d, data, size);
4595 void R_FrameData_SetMark(void)
4597 if (!r_framedata_mem)
4599 r_framedata_mem->mark = r_framedata_mem->current;
4602 void R_FrameData_ReturnToMark(void)
4604 if (!r_framedata_mem)
4606 r_framedata_mem->current = r_framedata_mem->mark;
4609 //==================================================================================
4611 // LordHavoc: animcache originally written by Echon, rewritten since then
4614 * Animation cache prevents re-generating mesh data for an animated model
4615 * multiple times in one frame for lighting, shadowing, reflections, etc.
4618 void R_AnimCache_Free(void)
4622 void R_AnimCache_ClearCache(void)
4625 entity_render_t *ent;
4627 for (i = 0;i < r_refdef.scene.numentities;i++)
4629 ent = r_refdef.scene.entities[i];
4630 ent->animcache_vertex3f = NULL;
4631 ent->animcache_normal3f = NULL;
4632 ent->animcache_svector3f = NULL;
4633 ent->animcache_tvector3f = NULL;
4634 ent->animcache_vertexmesh = NULL;
4635 ent->animcache_vertex3fbuffer = NULL;
4636 ent->animcache_vertexmeshbuffer = NULL;
4637 ent->animcache_skeletaltransform3x4 = NULL;
4641 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4645 // check if we need the meshbuffers
4646 if (!vid.useinterleavedarrays)
4649 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4650 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4651 // TODO: upload vertex3f buffer?
4652 if (ent->animcache_vertexmesh)
4654 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4655 for (i = 0;i < numvertices;i++)
4656 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4657 if (ent->animcache_svector3f)
4658 for (i = 0;i < numvertices;i++)
4659 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4660 if (ent->animcache_tvector3f)
4661 for (i = 0;i < numvertices;i++)
4662 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4663 if (ent->animcache_normal3f)
4664 for (i = 0;i < numvertices;i++)
4665 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4666 // TODO: upload vertexmeshbuffer?
4670 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4672 dp_model_t *model = ent->model;
4675 // cache skeletal animation data first (primarily for gpu-skinning)
4676 if (!ent->animcache_skeletaltransform3x4 && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4680 const skeleton_t *skeleton = ent->skeleton;
4681 const frameblend_t *frameblend = ent->frameblend;
4682 float *boneposerelative;
4684 static float bonepose[256][12];
4685 ent->animcache_skeletaltransform3x4 = R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4686 boneposerelative = ent->animcache_skeletaltransform3x4;
4687 if (skeleton && !skeleton->relativetransforms)
4689 // resolve hierarchy and make relative transforms (deforms) which the shader wants
4692 for (i = 0;i < model->num_bones;i++)
4694 Matrix4x4_ToArray12FloatD3D(&skeleton->relativetransforms[i], m);
4695 if (model->data_bones[i].parent >= 0)
4696 R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
4698 memcpy(bonepose[i], m, sizeof(m));
4700 // create a relative deformation matrix to describe displacement
4701 // from the base mesh, which is used by the actual weighting
4702 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative + i * 12);
4707 for (i = 0;i < model->num_bones;i++)
4709 const short * RESTRICT pose7s = model->data_poses7s + 7 * (frameblend[0].subframe * model->num_bones + i);
4710 float lerp = frameblend[0].lerp,
4711 tx = pose7s[0], ty = pose7s[1], tz = pose7s[2],
4712 rx = pose7s[3] * lerp,
4713 ry = pose7s[4] * lerp,
4714 rz = pose7s[5] * lerp,
4715 rw = pose7s[6] * lerp,
4716 dx = tx*rw + ty*rz - tz*ry,
4717 dy = -tx*rz + ty*rw + tz*rx,
4718 dz = tx*ry - ty*rx + tz*rw,
4719 dw = -tx*rx - ty*ry - tz*rz,
4720 scale, sx, sy, sz, sw;
4721 for (blends = 1;blends < MAX_FRAMEBLENDS && frameblend[blends].lerp > 0;blends++)
4723 const short * RESTRICT pose7s = model->data_poses7s + 7 * (frameblend[blends].subframe * model->num_bones + i);
4724 float lerp = frameblend[blends].lerp,
4725 tx = pose7s[0], ty = pose7s[1], tz = pose7s[2],
4726 qx = pose7s[3], qy = pose7s[4], qz = pose7s[5], qw = pose7s[6];
4727 if(rx*qx + ry*qy + rz*qz + rw*qw < 0) lerp = -lerp;
4736 dx += tx*qw + ty*qz - tz*qy;
4737 dy += -tx*qz + ty*qw + tz*qx;
4738 dz += tx*qy - ty*qx + tz*qw;
4739 dw += -tx*qx - ty*qy - tz*qz;
4741 scale = 1.0f / (rx*rx + ry*ry + rz*rz + rw*rw);
4746 m[0] = sw*rw + sx*rx - sy*ry - sz*rz;
4747 m[1] = 2*(sx*ry - sw*rz);
4748 m[2] = 2*(sx*rz + sw*ry);
4749 m[3] = model->num_posescale*(dx*sw - dy*sz + dz*sy - dw*sx);
4750 m[4] = 2*(sx*ry + sw*rz);
4751 m[5] = sw*rw + sy*ry - sx*rx - sz*rz;
4752 m[6] = 2*(sy*rz - sw*rx);
4753 m[7] = model->num_posescale*(dx*sz + dy*sw - dz*sx - dw*sy);
4754 m[8] = 2*(sx*rz - sw*ry);
4755 m[9] = 2*(sy*rz + sw*rx);
4756 m[10] = sw*rw + sz*rz - sx*rx - sy*ry;
4757 m[11] = model->num_posescale*(dy*sx + dz*sw - dx*sy - dw*sz);
4758 if (i == r_skeletal_debugbone.integer)
4759 m[r_skeletal_debugbonecomponent.integer % 12] += r_skeletal_debugbonevalue.value;
4760 m[3] *= r_skeletal_debugtranslatex.value;
4761 m[7] *= r_skeletal_debugtranslatey.value;
4762 m[11] *= r_skeletal_debugtranslatez.value;
4763 if (model->data_bones[i].parent >= 0)
4764 R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
4766 memcpy(bonepose[i], m, sizeof(m));
4767 // create a relative deformation matrix to describe displacement
4768 // from the base mesh, which is used by the actual weighting
4769 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative + i * 12);
4774 // see if it's already cached this frame
4775 if (ent->animcache_vertex3f)
4777 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4778 if (wantnormals || wanttangents)
4780 if (ent->animcache_normal3f)
4781 wantnormals = false;
4782 if (ent->animcache_svector3f)
4783 wanttangents = false;
4784 if (wantnormals || wanttangents)
4786 numvertices = model->surfmesh.num_vertices;
4788 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4791 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4792 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4794 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4795 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4801 // see if this ent is worth caching
4802 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4804 // skip entity if the shader backend has a cheaper way
4805 if (model->surfmesh.data_skeletalindex4ub && r_glsl_skeletal.integer)
4807 switch (vid.renderpath)
4809 case RENDERPATH_GL20:
4811 case RENDERPATH_GL11:
4812 case RENDERPATH_GL13:
4813 case RENDERPATH_GLES1:
4814 case RENDERPATH_GLES2:
4815 case RENDERPATH_D3D9:
4816 case RENDERPATH_D3D10:
4817 case RENDERPATH_D3D11:
4818 case RENDERPATH_SOFT:
4822 // get some memory for this entity and generate mesh data
4823 numvertices = model->surfmesh.num_vertices;
4824 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4826 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4829 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4830 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4832 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4833 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4838 void R_AnimCache_CacheVisibleEntities(void)
4841 qboolean wantnormals = true;
4842 qboolean wanttangents = !r_showsurfaces.integer;
4844 switch(vid.renderpath)
4846 case RENDERPATH_GL20:
4847 case RENDERPATH_D3D9:
4848 case RENDERPATH_D3D10:
4849 case RENDERPATH_D3D11:
4850 case RENDERPATH_GLES2:
4852 case RENDERPATH_GL11:
4853 case RENDERPATH_GL13:
4854 case RENDERPATH_GLES1:
4855 wanttangents = false;
4857 case RENDERPATH_SOFT:
4861 if (r_shownormals.integer)
4862 wanttangents = wantnormals = true;
4864 // TODO: thread this
4865 // NOTE: R_PrepareRTLights() also caches entities
4867 for (i = 0;i < r_refdef.scene.numentities;i++)
4868 if (r_refdef.viewcache.entityvisible[i])
4869 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4872 //==================================================================================
4874 extern cvar_t r_overheadsprites_pushback;
4876 static void R_View_UpdateEntityLighting (void)
4879 entity_render_t *ent;
4880 vec3_t tempdiffusenormal, avg;
4881 vec_t f, fa, fd, fdd;
4882 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4884 for (i = 0;i < r_refdef.scene.numentities;i++)
4886 ent = r_refdef.scene.entities[i];
4888 // skip unseen models
4889 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
4893 if (ent->model && ent->model == cl.worldmodel)
4895 // TODO: use modellight for r_ambient settings on world?
4896 VectorSet(ent->modellight_ambient, 0, 0, 0);
4897 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4898 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4902 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
4904 // aleady updated by CSQC
4905 // TODO: force modellight on BSP models in this case?
4906 VectorCopy(ent->modellight_lightdir, tempdiffusenormal);
4910 // fetch the lighting from the worldmodel data
4911 VectorClear(ent->modellight_ambient);
4912 VectorClear(ent->modellight_diffuse);
4913 VectorClear(tempdiffusenormal);
4914 if (ent->flags & RENDER_LIGHT)
4917 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4919 // complete lightning for lit sprites
4920 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4921 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4923 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4924 org[2] = org[2] + r_overheadsprites_pushback.value;
4925 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4928 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4930 if(ent->flags & RENDER_EQUALIZE)
4932 // first fix up ambient lighting...
4933 if(r_equalize_entities_minambient.value > 0)
4935 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4938 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4939 if(fa < r_equalize_entities_minambient.value * fd)
4942 // fa'/fd' = minambient
4943 // fa'+0.25*fd' = fa+0.25*fd
4945 // fa' = fd' * minambient
4946 // fd'*(0.25+minambient) = fa+0.25*fd
4948 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4949 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4951 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4952 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
4953 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4954 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4959 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4961 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4962 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4966 // adjust brightness and saturation to target
4967 avg[0] = avg[1] = avg[2] = fa / f;
4968 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4969 avg[0] = avg[1] = avg[2] = fd / f;
4970 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4976 VectorSet(ent->modellight_ambient, 1, 1, 1);
4979 // move the light direction into modelspace coordinates for lighting code
4980 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4981 if(VectorLength2(ent->modellight_lightdir) == 0)
4982 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4983 VectorNormalize(ent->modellight_lightdir);
4987 #define MAX_LINEOFSIGHTTRACES 64
4989 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4992 vec3_t boxmins, boxmaxs;
4995 dp_model_t *model = r_refdef.scene.worldmodel;
4997 if (!model || !model->brush.TraceLineOfSight)
5000 // expand the box a little
5001 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
5002 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
5003 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
5004 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
5005 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
5006 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
5008 // return true if eye is inside enlarged box
5009 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
5013 VectorCopy(eye, start);
5014 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
5015 if (model->brush.TraceLineOfSight(model, start, end))
5018 // try various random positions
5019 for (i = 0;i < numsamples;i++)
5021 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5022 if (model->brush.TraceLineOfSight(model, start, end))
5030 static void R_View_UpdateEntityVisible (void)
5035 entity_render_t *ent;
5037 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
5038 : r_fb.water.hideplayer ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
5039 : (chase_active.integer || r_fb.water.renderingscene) ? RENDER_VIEWMODEL
5040 : RENDER_EXTERIORMODEL;
5041 if (!r_drawviewmodel.integer)
5042 renderimask |= RENDER_VIEWMODEL;
5043 if (!r_drawexteriormodel.integer)
5044 renderimask |= RENDER_EXTERIORMODEL;
5045 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5047 // worldmodel can check visibility
5048 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5049 for (i = 0;i < r_refdef.scene.numentities;i++)
5051 ent = r_refdef.scene.entities[i];
5052 if (!(ent->flags & renderimask))
5053 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)))
5054 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))
5055 r_refdef.viewcache.entityvisible[i] = true;
5060 // no worldmodel or it can't check visibility
5061 for (i = 0;i < r_refdef.scene.numentities;i++)
5063 ent = r_refdef.scene.entities[i];
5064 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));
5067 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
5068 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
5070 for (i = 0;i < r_refdef.scene.numentities;i++)
5072 if (!r_refdef.viewcache.entityvisible[i])
5074 ent = r_refdef.scene.entities[i];
5075 if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5077 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
5079 continue; // temp entities do pvs only
5080 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5081 ent->last_trace_visibility = realtime;
5082 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5083 r_refdef.viewcache.entityvisible[i] = 0;
5089 /// only used if skyrendermasked, and normally returns false
5090 static int R_DrawBrushModelsSky (void)
5093 entity_render_t *ent;
5096 for (i = 0;i < r_refdef.scene.numentities;i++)
5098 if (!r_refdef.viewcache.entityvisible[i])
5100 ent = r_refdef.scene.entities[i];
5101 if (!ent->model || !ent->model->DrawSky)
5103 ent->model->DrawSky(ent);
5109 static void R_DrawNoModel(entity_render_t *ent);
5110 static void R_DrawModels(void)
5113 entity_render_t *ent;
5115 for (i = 0;i < r_refdef.scene.numentities;i++)
5117 if (!r_refdef.viewcache.entityvisible[i])
5119 ent = r_refdef.scene.entities[i];
5120 r_refdef.stats.entities++;
5122 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5125 Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5126 Con_Printf("R_DrawModels\n");
5127 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]);
5128 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);
5129 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);
5132 if (ent->model && ent->model->Draw != NULL)
5133 ent->model->Draw(ent);
5139 static void R_DrawModelsDepth(void)
5142 entity_render_t *ent;
5144 for (i = 0;i < r_refdef.scene.numentities;i++)
5146 if (!r_refdef.viewcache.entityvisible[i])
5148 ent = r_refdef.scene.entities[i];
5149 if (ent->model && ent->model->DrawDepth != NULL)
5150 ent->model->DrawDepth(ent);
5154 static void R_DrawModelsDebug(void)
5157 entity_render_t *ent;
5159 for (i = 0;i < r_refdef.scene.numentities;i++)
5161 if (!r_refdef.viewcache.entityvisible[i])
5163 ent = r_refdef.scene.entities[i];
5164 if (ent->model && ent->model->DrawDebug != NULL)
5165 ent->model->DrawDebug(ent);
5169 static void R_DrawModelsAddWaterPlanes(void)
5172 entity_render_t *ent;
5174 for (i = 0;i < r_refdef.scene.numentities;i++)
5176 if (!r_refdef.viewcache.entityvisible[i])
5178 ent = r_refdef.scene.entities[i];
5179 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5180 ent->model->DrawAddWaterPlanes(ent);
5184 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}};
5186 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5188 if (r_hdr_irisadaptation.integer)
5193 vec3_t diffusenormal;
5195 vec_t brightness = 0.0f;
5200 VectorCopy(r_refdef.view.forward, forward);
5201 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5203 p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5204 p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5205 p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5206 R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5207 d = DotProduct(forward, diffusenormal);
5208 brightness += VectorLength(ambient);
5210 brightness += d * VectorLength(diffuse);
5212 brightness *= 1.0f / c;
5213 brightness += 0.00001f; // make sure it's never zero
5214 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5215 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5216 current = r_hdr_irisadaptation_value.value;
5218 current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5219 else if (current > goal)
5220 current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5221 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5222 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5224 else if (r_hdr_irisadaptation_value.value != 1.0f)
5225 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5228 static void R_View_SetFrustum(const int *scissor)
5231 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5232 vec3_t forward, left, up, origin, v;
5236 // flipped x coordinates (because x points left here)
5237 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5238 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5240 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5241 switch(vid.renderpath)
5243 case RENDERPATH_D3D9:
5244 case RENDERPATH_D3D10:
5245 case RENDERPATH_D3D11:
5246 // non-flipped y coordinates
5247 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5248 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5250 case RENDERPATH_SOFT:
5251 case RENDERPATH_GL11:
5252 case RENDERPATH_GL13:
5253 case RENDERPATH_GL20:
5254 case RENDERPATH_GLES1:
5255 case RENDERPATH_GLES2:
5256 // non-flipped y coordinates
5257 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5258 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5263 // we can't trust r_refdef.view.forward and friends in reflected scenes
5264 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5267 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5268 r_refdef.view.frustum[0].normal[1] = 0 - 0;
5269 r_refdef.view.frustum[0].normal[2] = -1 - 0;
5270 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5271 r_refdef.view.frustum[1].normal[1] = 0 + 0;
5272 r_refdef.view.frustum[1].normal[2] = -1 + 0;
5273 r_refdef.view.frustum[2].normal[0] = 0 - 0;
5274 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5275 r_refdef.view.frustum[2].normal[2] = -1 - 0;
5276 r_refdef.view.frustum[3].normal[0] = 0 + 0;
5277 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5278 r_refdef.view.frustum[3].normal[2] = -1 + 0;
5282 zNear = r_refdef.nearclip;
5283 nudge = 1.0 - 1.0 / (1<<23);
5284 r_refdef.view.frustum[4].normal[0] = 0 - 0;
5285 r_refdef.view.frustum[4].normal[1] = 0 - 0;
5286 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5287 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5288 r_refdef.view.frustum[5].normal[0] = 0 + 0;
5289 r_refdef.view.frustum[5].normal[1] = 0 + 0;
5290 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5291 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5297 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5298 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5299 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5300 r_refdef.view.frustum[0].dist = m[15] - m[12];
5302 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5303 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5304 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5305 r_refdef.view.frustum[1].dist = m[15] + m[12];
5307 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5308 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5309 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5310 r_refdef.view.frustum[2].dist = m[15] - m[13];
5312 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5313 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5314 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5315 r_refdef.view.frustum[3].dist = m[15] + m[13];
5317 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5318 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5319 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5320 r_refdef.view.frustum[4].dist = m[15] - m[14];
5322 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5323 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5324 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5325 r_refdef.view.frustum[5].dist = m[15] + m[14];
5328 if (r_refdef.view.useperspective)
5330 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5331 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]);
5332 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]);
5333 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]);
5334 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]);
5336 // then the normals from the corners relative to origin
5337 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5338 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5339 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5340 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5342 // in a NORMAL view, forward cross left == up
5343 // in a REFLECTED view, forward cross left == down
5344 // so our cross products above need to be adjusted for a left handed coordinate system
5345 CrossProduct(forward, left, v);
5346 if(DotProduct(v, up) < 0)
5348 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5349 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5350 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5351 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5354 // Leaving those out was a mistake, those were in the old code, and they
5355 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5356 // I couldn't reproduce it after adding those normalizations. --blub
5357 VectorNormalize(r_refdef.view.frustum[0].normal);
5358 VectorNormalize(r_refdef.view.frustum[1].normal);
5359 VectorNormalize(r_refdef.view.frustum[2].normal);
5360 VectorNormalize(r_refdef.view.frustum[3].normal);
5362 // make the corners absolute
5363 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5364 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5365 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5366 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5369 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5371 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5372 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5373 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5374 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5375 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5379 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5380 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5381 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5382 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5383 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5384 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5385 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5386 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5387 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5388 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5390 r_refdef.view.numfrustumplanes = 5;
5392 if (r_refdef.view.useclipplane)
5394 r_refdef.view.numfrustumplanes = 6;
5395 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5398 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5399 PlaneClassify(r_refdef.view.frustum + i);
5401 // LordHavoc: note to all quake engine coders, Quake had a special case
5402 // for 90 degrees which assumed a square view (wrong), so I removed it,
5403 // Quake2 has it disabled as well.
5405 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5406 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5407 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5408 //PlaneClassify(&frustum[0]);
5410 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5411 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5412 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5413 //PlaneClassify(&frustum[1]);
5415 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5416 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5417 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5418 //PlaneClassify(&frustum[2]);
5420 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5421 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5422 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5423 //PlaneClassify(&frustum[3]);
5426 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5427 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5428 //PlaneClassify(&frustum[4]);
5431 static void R_View_UpdateWithScissor(const int *myscissor)
5433 R_Main_ResizeViewCache();
5434 R_View_SetFrustum(myscissor);
5435 R_View_WorldVisibility(r_refdef.view.useclipplane);
5436 R_View_UpdateEntityVisible();
5437 R_View_UpdateEntityLighting();
5440 static void R_View_Update(void)
5442 R_Main_ResizeViewCache();
5443 R_View_SetFrustum(NULL);
5444 R_View_WorldVisibility(r_refdef.view.useclipplane);
5445 R_View_UpdateEntityVisible();
5446 R_View_UpdateEntityLighting();
5449 float viewscalefpsadjusted = 1.0f;
5451 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5453 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5454 scale = bound(0.03125f, scale, 1.0f);
5455 *outwidth = (int)ceil(width * scale);
5456 *outheight = (int)ceil(height * scale);
5459 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5461 const float *customclipplane = NULL;
5463 int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5464 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5466 // LordHavoc: couldn't figure out how to make this approach the
5467 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5468 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5469 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5470 dist = r_refdef.view.clipplane.dist;
5471 plane[0] = r_refdef.view.clipplane.normal[0];
5472 plane[1] = r_refdef.view.clipplane.normal[1];
5473 plane[2] = r_refdef.view.clipplane.normal[2];
5475 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5478 //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5479 rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5481 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5482 if (!r_refdef.view.useperspective)
5483 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);
5484 else if (vid.stencil && r_useinfinitefarclip.integer)
5485 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);
5487 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);
5488 R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5489 R_SetViewport(&r_refdef.view.viewport);
5490 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5492 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5493 float screenplane[4];
5494 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5495 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5496 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5497 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5498 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5502 void R_EntityMatrix(const matrix4x4_t *matrix)
5504 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5506 gl_modelmatrixchanged = false;
5507 gl_modelmatrix = *matrix;
5508 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5509 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5510 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5511 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5513 switch(vid.renderpath)
5515 case RENDERPATH_D3D9:
5517 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5518 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5521 case RENDERPATH_D3D10:
5522 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5524 case RENDERPATH_D3D11:
5525 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5527 case RENDERPATH_GL11:
5528 case RENDERPATH_GL13:
5529 case RENDERPATH_GLES1:
5530 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5532 case RENDERPATH_SOFT:
5533 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5534 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5536 case RENDERPATH_GL20:
5537 case RENDERPATH_GLES2:
5538 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5539 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5545 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5547 r_viewport_t viewport;
5551 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5552 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);
5553 R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5554 R_SetViewport(&viewport);
5555 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5556 GL_Color(1, 1, 1, 1);
5557 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5558 GL_BlendFunc(GL_ONE, GL_ZERO);
5559 GL_ScissorTest(false);
5560 GL_DepthMask(false);
5561 GL_DepthRange(0, 1);
5562 GL_DepthTest(false);
5563 GL_DepthFunc(GL_LEQUAL);
5564 R_EntityMatrix(&identitymatrix);
5565 R_Mesh_ResetTextureState();
5566 GL_PolygonOffset(0, 0);
5567 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5568 switch(vid.renderpath)
5570 case RENDERPATH_GL11:
5571 case RENDERPATH_GL13:
5572 case RENDERPATH_GL20:
5573 case RENDERPATH_GLES1:
5574 case RENDERPATH_GLES2:
5575 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5577 case RENDERPATH_D3D9:
5578 case RENDERPATH_D3D10:
5579 case RENDERPATH_D3D11:
5580 case RENDERPATH_SOFT:
5583 GL_CullFace(GL_NONE);
5588 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5592 R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5595 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5599 R_SetupView(true, fbo, depthtexture, colortexture);
5600 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5601 GL_Color(1, 1, 1, 1);
5602 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5603 GL_BlendFunc(GL_ONE, GL_ZERO);
5604 GL_ScissorTest(true);
5606 GL_DepthRange(0, 1);
5608 GL_DepthFunc(GL_LEQUAL);
5609 R_EntityMatrix(&identitymatrix);
5610 R_Mesh_ResetTextureState();
5611 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5612 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5613 switch(vid.renderpath)
5615 case RENDERPATH_GL11:
5616 case RENDERPATH_GL13:
5617 case RENDERPATH_GL20:
5618 case RENDERPATH_GLES1:
5619 case RENDERPATH_GLES2:
5620 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5622 case RENDERPATH_D3D9:
5623 case RENDERPATH_D3D10:
5624 case RENDERPATH_D3D11:
5625 case RENDERPATH_SOFT:
5628 GL_CullFace(r_refdef.view.cullface_back);
5633 R_RenderView_UpdateViewVectors
5636 void R_RenderView_UpdateViewVectors(void)
5638 // break apart the view matrix into vectors for various purposes
5639 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5640 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5641 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5642 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5643 // make an inverted copy of the view matrix for tracking sprites
5644 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5647 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5648 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5650 static void R_Water_StartFrame(void)
5653 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5654 r_waterstate_waterplane_t *p;
5655 qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
5657 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5660 switch(vid.renderpath)
5662 case RENDERPATH_GL20:
5663 case RENDERPATH_D3D9:
5664 case RENDERPATH_D3D10:
5665 case RENDERPATH_D3D11:
5666 case RENDERPATH_SOFT:
5667 case RENDERPATH_GLES2:
5669 case RENDERPATH_GL11:
5670 case RENDERPATH_GL13:
5671 case RENDERPATH_GLES1:
5675 // set waterwidth and waterheight to the water resolution that will be
5676 // used (often less than the screen resolution for faster rendering)
5677 R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5679 // calculate desired texture sizes
5680 // can't use water if the card does not support the texture size
5681 if (!r_water.integer || r_showsurfaces.integer)
5682 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5683 else if (vid.support.arb_texture_non_power_of_two)
5685 texturewidth = waterwidth;
5686 textureheight = waterheight;
5687 camerawidth = waterwidth;
5688 cameraheight = waterheight;
5692 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5693 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5694 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5695 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5698 // allocate textures as needed
5699 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))
5701 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5702 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5704 if (p->texture_refraction)
5705 R_FreeTexture(p->texture_refraction);
5706 p->texture_refraction = NULL;
5707 if (p->fbo_refraction)
5708 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5709 p->fbo_refraction = 0;
5710 if (p->texture_reflection)
5711 R_FreeTexture(p->texture_reflection);
5712 p->texture_reflection = NULL;
5713 if (p->fbo_reflection)
5714 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5715 p->fbo_reflection = 0;
5716 if (p->texture_camera)
5717 R_FreeTexture(p->texture_camera);
5718 p->texture_camera = NULL;
5720 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5723 memset(&r_fb.water, 0, sizeof(r_fb.water));
5724 r_fb.water.texturewidth = texturewidth;
5725 r_fb.water.textureheight = textureheight;
5726 r_fb.water.camerawidth = camerawidth;
5727 r_fb.water.cameraheight = cameraheight;
5730 if (r_fb.water.texturewidth)
5732 int scaledwidth, scaledheight;
5734 r_fb.water.enabled = true;
5736 // water resolution is usually reduced
5737 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5738 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5739 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5741 // set up variables that will be used in shader setup
5742 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5743 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5744 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5745 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5748 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5749 r_fb.water.numwaterplanes = 0;
5752 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5754 int planeindex, bestplaneindex, vertexindex;
5755 vec3_t mins, maxs, normal, center, v, n;
5756 vec_t planescore, bestplanescore;
5758 r_waterstate_waterplane_t *p;
5759 texture_t *t = R_GetCurrentTexture(surface->texture);
5761 rsurface.texture = t;
5762 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5763 // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5764 if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5766 // average the vertex normals, find the surface bounds (after deformvertexes)
5767 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5768 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5769 VectorCopy(n, normal);
5770 VectorCopy(v, mins);
5771 VectorCopy(v, maxs);
5772 for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5774 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5775 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5776 VectorAdd(normal, n, normal);
5777 mins[0] = min(mins[0], v[0]);
5778 mins[1] = min(mins[1], v[1]);
5779 mins[2] = min(mins[2], v[2]);
5780 maxs[0] = max(maxs[0], v[0]);
5781 maxs[1] = max(maxs[1], v[1]);
5782 maxs[2] = max(maxs[2], v[2]);
5784 VectorNormalize(normal);
5785 VectorMAM(0.5f, mins, 0.5f, maxs, center);
5787 VectorCopy(normal, plane.normal);
5788 VectorNormalize(plane.normal);
5789 plane.dist = DotProduct(center, plane.normal);
5790 PlaneClassify(&plane);
5791 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5793 // skip backfaces (except if nocullface is set)
5794 // if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5796 VectorNegate(plane.normal, plane.normal);
5798 PlaneClassify(&plane);
5802 // find a matching plane if there is one
5803 bestplaneindex = -1;
5804 bestplanescore = 1048576.0f;
5805 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5807 if(p->camera_entity == t->camera_entity)
5809 planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5810 if (bestplaneindex < 0 || bestplanescore > planescore)
5812 bestplaneindex = planeindex;
5813 bestplanescore = planescore;
5817 planeindex = bestplaneindex;
5818 p = r_fb.water.waterplanes + planeindex;
5820 // if this surface does not fit any known plane rendered this frame, add one
5821 if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5823 // store the new plane
5824 planeindex = r_fb.water.numwaterplanes++;
5825 p = r_fb.water.waterplanes + planeindex;
5827 // clear materialflags and pvs
5828 p->materialflags = 0;
5829 p->pvsvalid = false;
5830 p->camera_entity = t->camera_entity;
5831 VectorCopy(mins, p->mins);
5832 VectorCopy(maxs, p->maxs);
5836 // merge mins/maxs when we're adding this surface to the plane
5837 p->mins[0] = min(p->mins[0], mins[0]);
5838 p->mins[1] = min(p->mins[1], mins[1]);
5839 p->mins[2] = min(p->mins[2], mins[2]);
5840 p->maxs[0] = max(p->maxs[0], maxs[0]);
5841 p->maxs[1] = max(p->maxs[1], maxs[1]);
5842 p->maxs[2] = max(p->maxs[2], maxs[2]);
5844 // merge this surface's materialflags into the waterplane
5845 p->materialflags |= t->currentmaterialflags;
5846 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5848 // merge this surface's PVS into the waterplane
5849 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5850 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5852 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5858 extern cvar_t r_drawparticles;
5859 extern cvar_t r_drawdecals;
5861 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5864 r_refdef_view_t originalview;
5865 r_refdef_view_t myview;
5866 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;
5867 r_waterstate_waterplane_t *p;
5869 qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
5872 originalview = r_refdef.view;
5874 // lowquality hack, temporarily shut down some cvars and restore afterwards
5875 qualityreduction = r_water_lowquality.integer;
5876 if (qualityreduction > 0)
5878 if (qualityreduction >= 1)
5880 old_r_shadows = r_shadows.integer;
5881 old_r_worldrtlight = r_shadow_realtime_world.integer;
5882 old_r_dlight = r_shadow_realtime_dlight.integer;
5883 Cvar_SetValueQuick(&r_shadows, 0);
5884 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5885 Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5887 if (qualityreduction >= 2)
5889 old_r_dynamic = r_dynamic.integer;
5890 old_r_particles = r_drawparticles.integer;
5891 old_r_decals = r_drawdecals.integer;
5892 Cvar_SetValueQuick(&r_dynamic, 0);
5893 Cvar_SetValueQuick(&r_drawparticles, 0);
5894 Cvar_SetValueQuick(&r_drawdecals, 0);
5898 // make sure enough textures are allocated
5899 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5901 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5903 if (!p->texture_refraction)
5904 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);
5905 if (!p->texture_refraction)
5909 if (r_fb.water.depthtexture == NULL)
5910 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5911 if (p->fbo_refraction == 0)
5912 p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
5915 else if (p->materialflags & MATERIALFLAG_CAMERA)
5917 if (!p->texture_camera)
5918 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);
5919 if (!p->texture_camera)
5923 if (r_fb.water.depthtexture == NULL)
5924 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5925 if (p->fbo_camera == 0)
5926 p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
5930 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5932 if (!p->texture_reflection)
5933 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);
5934 if (!p->texture_reflection)
5938 if (r_fb.water.depthtexture == NULL)
5939 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5940 if (p->fbo_reflection == 0)
5941 p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
5947 r_refdef.view = originalview;
5948 r_refdef.view.showdebug = false;
5949 r_refdef.view.width = r_fb.water.waterwidth;
5950 r_refdef.view.height = r_fb.water.waterheight;
5951 r_refdef.view.useclipplane = true;
5952 myview = r_refdef.view;
5953 r_fb.water.renderingscene = true;
5954 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5956 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5958 r_refdef.view = myview;
5959 if(r_water_scissormode.integer)
5961 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5962 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5963 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5966 // render reflected scene and copy into texture
5967 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5968 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5969 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5970 r_refdef.view.clipplane = p->plane;
5971 // reverse the cullface settings for this render
5972 r_refdef.view.cullface_front = GL_FRONT;
5973 r_refdef.view.cullface_back = GL_BACK;
5974 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5976 r_refdef.view.usecustompvs = true;
5978 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5980 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5983 r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
5984 R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5985 R_ClearScreen(r_refdef.fogenabled);
5986 if(r_water_scissormode.integer & 2)
5987 R_View_UpdateWithScissor(myscissor);
5990 R_AnimCache_CacheVisibleEntities();
5991 if(r_water_scissormode.integer & 1)
5992 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5993 R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5995 if (!p->fbo_reflection)
5996 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);
5997 r_fb.water.hideplayer = false;
6000 // render the normal view scene and copy into texture
6001 // (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)
6002 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6004 r_refdef.view = myview;
6005 if(r_water_scissormode.integer)
6007 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6008 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6009 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6012 r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
6014 r_refdef.view.clipplane = p->plane;
6015 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6016 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6018 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6020 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6021 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6022 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6023 R_RenderView_UpdateViewVectors();
6024 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6026 r_refdef.view.usecustompvs = true;
6027 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);
6031 PlaneClassify(&r_refdef.view.clipplane);
6033 R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6034 R_ClearScreen(r_refdef.fogenabled);
6035 if(r_water_scissormode.integer & 2)
6036 R_View_UpdateWithScissor(myscissor);
6039 R_AnimCache_CacheVisibleEntities();
6040 if(r_water_scissormode.integer & 1)
6041 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6042 R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6044 if (!p->fbo_refraction)
6045 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);
6046 r_fb.water.hideplayer = false;
6048 else if (p->materialflags & MATERIALFLAG_CAMERA)
6050 r_refdef.view = myview;
6052 r_refdef.view.clipplane = p->plane;
6053 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6054 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6056 r_refdef.view.width = r_fb.water.camerawidth;
6057 r_refdef.view.height = r_fb.water.cameraheight;
6058 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6059 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6060 r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6061 r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6063 if(p->camera_entity)
6065 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6066 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6069 // note: all of the view is used for displaying... so
6070 // there is no use in scissoring
6072 // reverse the cullface settings for this render
6073 r_refdef.view.cullface_front = GL_FRONT;
6074 r_refdef.view.cullface_back = GL_BACK;
6075 // also reverse the view matrix
6076 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
6077 R_RenderView_UpdateViewVectors();
6078 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6080 r_refdef.view.usecustompvs = true;
6081 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);
6084 // camera needs no clipplane
6085 r_refdef.view.useclipplane = false;
6087 PlaneClassify(&r_refdef.view.clipplane);
6089 r_fb.water.hideplayer = false;
6091 R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6092 R_ClearScreen(r_refdef.fogenabled);
6094 R_AnimCache_CacheVisibleEntities();
6095 R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6098 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);
6099 r_fb.water.hideplayer = false;
6103 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6104 r_fb.water.renderingscene = false;
6105 r_refdef.view = originalview;
6106 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6107 if (!r_fb.water.depthtexture)
6108 R_ClearScreen(r_refdef.fogenabled);
6110 R_AnimCache_CacheVisibleEntities();
6113 r_refdef.view = originalview;
6114 r_fb.water.renderingscene = false;
6115 Cvar_SetValueQuick(&r_water, 0);
6116 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
6118 // lowquality hack, restore cvars
6119 if (qualityreduction > 0)
6121 if (qualityreduction >= 1)
6123 Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6124 Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6125 Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6127 if (qualityreduction >= 2)
6129 Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6130 Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6131 Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6136 static void R_Bloom_StartFrame(void)
6139 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6140 int viewwidth, viewheight;
6141 qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6142 textype_t textype = TEXTYPE_COLORBUFFER;
6144 switch (vid.renderpath)
6146 case RENDERPATH_GL20:
6147 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6148 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6150 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6151 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6154 case RENDERPATH_GL11:
6155 case RENDERPATH_GL13:
6156 case RENDERPATH_GLES1:
6157 case RENDERPATH_GLES2:
6158 case RENDERPATH_D3D9:
6159 case RENDERPATH_D3D10:
6160 case RENDERPATH_D3D11:
6161 r_fb.usedepthtextures = false;
6163 case RENDERPATH_SOFT:
6164 r_fb.usedepthtextures = true;
6168 if (r_viewscale_fpsscaling.integer)
6170 double actualframetime;
6171 double targetframetime;
6173 actualframetime = r_refdef.lastdrawscreentime;
6174 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6175 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6176 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6177 if (r_viewscale_fpsscaling_stepsize.value > 0)
6178 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6179 viewscalefpsadjusted += adjust;
6180 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6183 viewscalefpsadjusted = 1.0f;
6185 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6187 switch(vid.renderpath)
6189 case RENDERPATH_GL20:
6190 case RENDERPATH_D3D9:
6191 case RENDERPATH_D3D10:
6192 case RENDERPATH_D3D11:
6193 case RENDERPATH_SOFT:
6194 case RENDERPATH_GLES2:
6196 case RENDERPATH_GL11:
6197 case RENDERPATH_GL13:
6198 case RENDERPATH_GLES1:
6202 // set bloomwidth and bloomheight to the bloom resolution that will be
6203 // used (often less than the screen resolution for faster rendering)
6204 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6205 r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6206 r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6207 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6208 r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6210 // calculate desired texture sizes
6211 if (vid.support.arb_texture_non_power_of_two)
6213 screentexturewidth = vid.width;
6214 screentextureheight = vid.height;
6215 bloomtexturewidth = r_fb.bloomwidth;
6216 bloomtextureheight = r_fb.bloomheight;
6220 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
6221 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
6222 for (bloomtexturewidth = 1;bloomtexturewidth < r_fb.bloomwidth ;bloomtexturewidth *= 2);
6223 for (bloomtextureheight = 1;bloomtextureheight < r_fb.bloomheight;bloomtextureheight *= 2);
6226 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))
6228 Cvar_SetValueQuick(&r_bloom, 0);
6229 Cvar_SetValueQuick(&r_motionblur, 0);
6230 Cvar_SetValueQuick(&r_damageblur, 0);
6233 if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6235 && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6237 && r_viewscale.value == 1.0f
6238 && !r_viewscale_fpsscaling.integer)
6239 screentexturewidth = screentextureheight = 0;
6240 if (!r_bloom.integer)
6241 bloomtexturewidth = bloomtextureheight = 0;
6243 // allocate textures as needed
6244 if (r_fb.screentexturewidth != screentexturewidth
6245 || r_fb.screentextureheight != screentextureheight
6246 || r_fb.bloomtexturewidth != bloomtexturewidth
6247 || r_fb.bloomtextureheight != bloomtextureheight
6248 || r_fb.textype != textype
6249 || useviewfbo != (r_fb.fbo != 0))
6251 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6253 if (r_fb.bloomtexture[i])
6254 R_FreeTexture(r_fb.bloomtexture[i]);
6255 r_fb.bloomtexture[i] = NULL;
6257 if (r_fb.bloomfbo[i])
6258 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6259 r_fb.bloomfbo[i] = 0;
6263 R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6266 if (r_fb.colortexture)
6267 R_FreeTexture(r_fb.colortexture);
6268 r_fb.colortexture = NULL;
6270 if (r_fb.depthtexture)
6271 R_FreeTexture(r_fb.depthtexture);
6272 r_fb.depthtexture = NULL;
6274 if (r_fb.ghosttexture)
6275 R_FreeTexture(r_fb.ghosttexture);
6276 r_fb.ghosttexture = NULL;
6278 r_fb.screentexturewidth = screentexturewidth;
6279 r_fb.screentextureheight = screentextureheight;
6280 r_fb.bloomtexturewidth = bloomtexturewidth;
6281 r_fb.bloomtextureheight = bloomtextureheight;
6282 r_fb.textype = textype;
6284 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6286 if (r_motionblur.value > 0 || r_damageblur.value > 0)
6287 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);
6288 r_fb.ghosttexture_valid = false;
6289 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);
6292 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6293 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6294 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6298 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6300 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6302 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);
6304 r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6309 // bloom texture is a different resolution
6310 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6311 r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6312 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6313 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6314 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6316 // set up a texcoord array for the full resolution screen image
6317 // (we have to keep this around to copy back during final render)
6318 r_fb.screentexcoord2f[0] = 0;
6319 r_fb.screentexcoord2f[1] = (float)viewheight / (float)r_fb.screentextureheight;
6320 r_fb.screentexcoord2f[2] = (float)viewwidth / (float)r_fb.screentexturewidth;
6321 r_fb.screentexcoord2f[3] = (float)viewheight / (float)r_fb.screentextureheight;
6322 r_fb.screentexcoord2f[4] = (float)viewwidth / (float)r_fb.screentexturewidth;
6323 r_fb.screentexcoord2f[5] = 0;
6324 r_fb.screentexcoord2f[6] = 0;
6325 r_fb.screentexcoord2f[7] = 0;
6329 for (i = 1;i < 8;i += 2)
6331 r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6335 // set up a texcoord array for the reduced resolution bloom image
6336 // (which will be additive blended over the screen image)
6337 r_fb.bloomtexcoord2f[0] = 0;
6338 r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6339 r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6340 r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6341 r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6342 r_fb.bloomtexcoord2f[5] = 0;
6343 r_fb.bloomtexcoord2f[6] = 0;
6344 r_fb.bloomtexcoord2f[7] = 0;
6346 switch(vid.renderpath)
6348 case RENDERPATH_GL11:
6349 case RENDERPATH_GL13:
6350 case RENDERPATH_GL20:
6351 case RENDERPATH_SOFT:
6352 case RENDERPATH_GLES1:
6353 case RENDERPATH_GLES2:
6355 case RENDERPATH_D3D9:
6356 case RENDERPATH_D3D10:
6357 case RENDERPATH_D3D11:
6358 for (i = 0;i < 4;i++)
6360 r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6361 r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6362 r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6363 r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6368 R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6371 r_refdef.view.clear = true;
6374 static void R_Bloom_MakeTexture(void)
6377 float xoffset, yoffset, r, brighten;
6379 float colorscale = r_bloom_colorscale.value;
6381 r_refdef.stats.bloom++;
6384 // this copy is unnecessary since it happens in R_BlendView already
6387 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);
6388 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6392 // scale down screen texture to the bloom texture size
6394 r_fb.bloomindex = 0;
6395 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6396 R_SetViewport(&r_fb.bloomviewport);
6397 GL_DepthTest(false);
6398 GL_BlendFunc(GL_ONE, GL_ZERO);
6399 GL_Color(colorscale, colorscale, colorscale, 1);
6400 // 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...
6401 switch(vid.renderpath)
6403 case RENDERPATH_GL11:
6404 case RENDERPATH_GL13:
6405 case RENDERPATH_GL20:
6406 case RENDERPATH_GLES1:
6407 case RENDERPATH_GLES2:
6408 case RENDERPATH_SOFT:
6409 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6411 case RENDERPATH_D3D9:
6412 case RENDERPATH_D3D10:
6413 case RENDERPATH_D3D11:
6414 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6417 // TODO: do boxfilter scale-down in shader?
6418 R_SetupShader_Generic(r_fb.colortexture, 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_fb.bloomwidth * r_fb.bloomheight;
6422 // we now have a properly scaled bloom image
6423 if (!r_fb.bloomfbo[r_fb.bloomindex])
6425 // copy it into the bloom texture
6426 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);
6427 r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6430 // multiply bloom image by itself as many times as desired
6431 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6433 intex = r_fb.bloomtexture[r_fb.bloomindex];
6434 r_fb.bloomindex ^= 1;
6435 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6437 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6438 if (!r_fb.bloomfbo[r_fb.bloomindex])
6440 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6441 GL_Color(r,r,r,1); // apply fix factor
6446 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6447 GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6448 GL_Color(1,1,1,1); // no fix factor supported here
6450 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6451 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6452 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6453 r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6455 if (!r_fb.bloomfbo[r_fb.bloomindex])
6457 // copy the darkened image to a texture
6458 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);
6459 r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6463 range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6464 brighten = r_bloom_brighten.value;
6465 brighten = sqrt(brighten);
6467 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6469 for (dir = 0;dir < 2;dir++)
6471 intex = r_fb.bloomtexture[r_fb.bloomindex];
6472 r_fb.bloomindex ^= 1;
6473 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6474 // blend on at multiple vertical offsets to achieve a vertical blur
6475 // TODO: do offset blends using GLSL
6476 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6477 GL_BlendFunc(GL_ONE, GL_ZERO);
6478 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6479 for (x = -range;x <= range;x++)
6481 if (!dir){xoffset = 0;yoffset = x;}
6482 else {xoffset = x;yoffset = 0;}
6483 xoffset /= (float)r_fb.bloomtexturewidth;
6484 yoffset /= (float)r_fb.bloomtextureheight;
6485 // compute a texcoord array with the specified x and y offset
6486 r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6487 r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6488 r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6489 r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6490 r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6491 r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6492 r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6493 r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6494 // this r value looks like a 'dot' particle, fading sharply to
6495 // black at the edges
6496 // (probably not realistic but looks good enough)
6497 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6498 //r = brighten/(range*2+1);
6499 r = brighten / (range * 2 + 1);
6501 r *= (1 - x*x/(float)(range*range));
6502 GL_Color(r, r, r, 1);
6503 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6504 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6505 r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6506 GL_BlendFunc(GL_ONE, GL_ONE);
6509 if (!r_fb.bloomfbo[r_fb.bloomindex])
6511 // copy the vertically or horizontally blurred bloom view to a texture
6512 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);
6513 r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6518 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6520 unsigned int permutation;
6521 float uservecs[4][4];
6523 R_EntityMatrix(&identitymatrix);
6525 switch (vid.renderpath)
6527 case RENDERPATH_GL20:
6528 case RENDERPATH_D3D9:
6529 case RENDERPATH_D3D10:
6530 case RENDERPATH_D3D11:
6531 case RENDERPATH_SOFT:
6532 case RENDERPATH_GLES2:
6534 (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6535 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6536 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6537 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6538 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6540 if (r_fb.colortexture)
6544 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);
6545 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6548 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6550 // declare variables
6551 float blur_factor, blur_mouseaccel, blur_velocity;
6552 static float blur_average;
6553 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6555 // set a goal for the factoring
6556 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value)
6557 / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6558 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value)
6559 / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6560 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value)
6561 + (blur_mouseaccel * r_motionblur_mousefactor.value));
6563 // from the goal, pick an averaged value between goal and last value
6564 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6565 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6567 // enforce minimum amount of blur
6568 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6570 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6572 // calculate values into a standard alpha
6573 cl.motionbluralpha = 1 - exp(-
6575 (r_motionblur.value * blur_factor / 80)
6577 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6580 max(0.0001, cl.time - cl.oldtime) // fps independent
6583 // randomization for the blur value to combat persistent ghosting
6584 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6585 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6588 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6589 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6591 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6592 GL_Color(1, 1, 1, cl.motionbluralpha);
6593 switch(vid.renderpath)
6595 case RENDERPATH_GL11:
6596 case RENDERPATH_GL13:
6597 case RENDERPATH_GL20:
6598 case RENDERPATH_GLES1:
6599 case RENDERPATH_GLES2:
6600 case RENDERPATH_SOFT:
6601 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6603 case RENDERPATH_D3D9:
6604 case RENDERPATH_D3D10:
6605 case RENDERPATH_D3D11:
6606 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6609 R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6610 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6611 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6614 // updates old view angles for next pass
6615 VectorCopy(cl.viewangles, blur_oldangles);
6617 // copy view into the ghost texture
6618 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);
6619 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6620 r_fb.ghosttexture_valid = true;
6625 // no r_fb.colortexture means we're rendering to the real fb
6626 // we may still have to do view tint...
6627 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6629 // apply a color tint to the whole view
6630 R_ResetViewRendering2D(0, NULL, NULL);
6631 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6632 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6633 R_SetupShader_Generic_NoTexture(false, true);
6634 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6635 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6637 break; // no screen processing, no bloom, skip it
6640 if (r_fb.bloomtexture[0])
6642 // make the bloom texture
6643 R_Bloom_MakeTexture();
6646 #if _MSC_VER >= 1400
6647 #define sscanf sscanf_s
6649 memset(uservecs, 0, sizeof(uservecs));
6650 if (r_glsl_postprocess_uservec1_enable.integer)
6651 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6652 if (r_glsl_postprocess_uservec2_enable.integer)
6653 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6654 if (r_glsl_postprocess_uservec3_enable.integer)
6655 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6656 if (r_glsl_postprocess_uservec4_enable.integer)
6657 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6659 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6660 GL_Color(1, 1, 1, 1);
6661 GL_BlendFunc(GL_ONE, GL_ZERO);
6663 switch(vid.renderpath)
6665 case RENDERPATH_GL20:
6666 case RENDERPATH_GLES2:
6667 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6668 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6669 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_fb.colortexture);
6670 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_fb.bloomtexture[r_fb.bloomindex]);
6671 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6672 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]);
6673 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6674 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]);
6675 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]);
6676 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]);
6677 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]);
6678 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6679 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6680 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);
6682 case RENDERPATH_D3D9:
6684 // 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...
6685 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6686 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6687 R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture);
6688 R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]);
6689 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6690 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6691 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6692 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6693 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6694 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6695 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6696 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6697 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6698 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6701 case RENDERPATH_D3D10:
6702 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6704 case RENDERPATH_D3D11:
6705 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6707 case RENDERPATH_SOFT:
6708 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6709 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6710 R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture);
6711 R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]);
6712 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6713 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6714 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6715 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6716 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6717 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6718 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6719 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6720 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6721 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6726 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6727 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6729 case RENDERPATH_GL11:
6730 case RENDERPATH_GL13:
6731 case RENDERPATH_GLES1:
6732 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6734 // apply a color tint to the whole view
6735 R_ResetViewRendering2D(0, NULL, NULL);
6736 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6737 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6738 R_SetupShader_Generic_NoTexture(false, true);
6739 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6740 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6746 matrix4x4_t r_waterscrollmatrix;
6748 void R_UpdateFog(void)
6751 if (gamemode == GAME_NEHAHRA)
6753 if (gl_fogenable.integer)
6755 r_refdef.oldgl_fogenable = true;
6756 r_refdef.fog_density = gl_fogdensity.value;
6757 r_refdef.fog_red = gl_fogred.value;
6758 r_refdef.fog_green = gl_foggreen.value;
6759 r_refdef.fog_blue = gl_fogblue.value;
6760 r_refdef.fog_alpha = 1;
6761 r_refdef.fog_start = 0;
6762 r_refdef.fog_end = gl_skyclip.value;
6763 r_refdef.fog_height = 1<<30;
6764 r_refdef.fog_fadedepth = 128;
6766 else if (r_refdef.oldgl_fogenable)
6768 r_refdef.oldgl_fogenable = false;
6769 r_refdef.fog_density = 0;
6770 r_refdef.fog_red = 0;
6771 r_refdef.fog_green = 0;
6772 r_refdef.fog_blue = 0;
6773 r_refdef.fog_alpha = 0;
6774 r_refdef.fog_start = 0;
6775 r_refdef.fog_end = 0;
6776 r_refdef.fog_height = 1<<30;
6777 r_refdef.fog_fadedepth = 128;
6782 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6783 r_refdef.fog_start = max(0, r_refdef.fog_start);
6784 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6786 if (r_refdef.fog_density && r_drawfog.integer)
6788 r_refdef.fogenabled = true;
6789 // this is the point where the fog reaches 0.9986 alpha, which we
6790 // consider a good enough cutoff point for the texture
6791 // (0.9986 * 256 == 255.6)
6792 if (r_fog_exp2.integer)
6793 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6795 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6796 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6797 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6798 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6799 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6800 R_BuildFogHeightTexture();
6801 // fog color was already set
6802 // update the fog texture
6803 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)
6804 R_BuildFogTexture();
6805 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6806 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6809 r_refdef.fogenabled = false;
6812 if (r_refdef.fog_density)
6814 r_refdef.fogcolor[0] = r_refdef.fog_red;
6815 r_refdef.fogcolor[1] = r_refdef.fog_green;
6816 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6818 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6819 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6820 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6821 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6825 VectorCopy(r_refdef.fogcolor, fogvec);
6826 // color.rgb *= ContrastBoost * SceneBrightness;
6827 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6828 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6829 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6830 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6835 void R_UpdateVariables(void)
6839 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6841 r_refdef.farclip = r_farclip_base.value;
6842 if (r_refdef.scene.worldmodel)
6843 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6844 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6846 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6847 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6848 r_refdef.polygonfactor = 0;
6849 r_refdef.polygonoffset = 0;
6850 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6851 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6853 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6854 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6855 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6856 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6857 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6858 if (FAKELIGHT_ENABLED)
6860 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6862 else if (r_refdef.scene.worldmodel)
6864 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
6866 if (r_showsurfaces.integer)
6868 r_refdef.scene.rtworld = false;
6869 r_refdef.scene.rtworldshadows = false;
6870 r_refdef.scene.rtdlight = false;
6871 r_refdef.scene.rtdlightshadows = false;
6872 r_refdef.lightmapintensity = 0;
6875 switch(vid.renderpath)
6877 case RENDERPATH_GL20:
6878 case RENDERPATH_D3D9:
6879 case RENDERPATH_D3D10:
6880 case RENDERPATH_D3D11:
6881 case RENDERPATH_SOFT:
6882 case RENDERPATH_GLES2:
6883 if(v_glslgamma.integer && !vid_gammatables_trivial)
6885 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6887 // build GLSL gamma texture
6888 #define RAMPWIDTH 256
6889 unsigned short ramp[RAMPWIDTH * 3];
6890 unsigned char rampbgr[RAMPWIDTH][4];
6893 r_texture_gammaramps_serial = vid_gammatables_serial;
6895 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6896 for(i = 0; i < RAMPWIDTH; ++i)
6898 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6899 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6900 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6903 if (r_texture_gammaramps)
6905 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6909 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6915 // remove GLSL gamma texture
6918 case RENDERPATH_GL11:
6919 case RENDERPATH_GL13:
6920 case RENDERPATH_GLES1:
6925 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6926 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6932 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6933 if( scenetype != r_currentscenetype ) {
6934 // store the old scenetype
6935 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6936 r_currentscenetype = scenetype;
6937 // move in the new scene
6938 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6947 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6949 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6950 if( scenetype == r_currentscenetype ) {
6951 return &r_refdef.scene;
6953 return &r_scenes_store[ scenetype ];
6957 static int R_SortEntities_Compare(const void *ap, const void *bp)
6959 const entity_render_t *a = *(const entity_render_t **)ap;
6960 const entity_render_t *b = *(const entity_render_t **)bp;
6963 if(a->model < b->model)
6965 if(a->model > b->model)
6969 // TODO possibly calculate the REAL skinnum here first using
6971 if(a->skinnum < b->skinnum)
6973 if(a->skinnum > b->skinnum)
6976 // everything we compared is equal
6979 static void R_SortEntities(void)
6981 // below or equal 2 ents, sorting never gains anything
6982 if(r_refdef.scene.numentities <= 2)
6985 qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6993 int dpsoftrast_test;
6994 extern cvar_t r_shadow_bouncegrid;
6995 void R_RenderView(void)
6997 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6999 rtexture_t *depthtexture;
7000 rtexture_t *colortexture;
7002 dpsoftrast_test = r_test.integer;
7004 if (r_timereport_active)
7005 R_TimeReport("start");
7006 r_textureframe++; // used only by R_GetCurrentTexture
7007 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7009 if(R_CompileShader_CheckStaticParms())
7012 if (!r_drawentities.integer)
7013 r_refdef.scene.numentities = 0;
7014 else if (r_sortentities.integer)
7017 R_AnimCache_ClearCache();
7018 R_FrameData_NewFrame();
7020 /* adjust for stereo display */
7021 if(R_Stereo_Active())
7023 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);
7024 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7027 if (r_refdef.view.isoverlay)
7029 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7030 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7031 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7032 R_TimeReport("depthclear");
7034 r_refdef.view.showdebug = false;
7036 r_fb.water.enabled = false;
7037 r_fb.water.numwaterplanes = 0;
7039 R_RenderScene(0, NULL, NULL);
7041 r_refdef.view.matrix = originalmatrix;
7047 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7049 r_refdef.view.matrix = originalmatrix;
7053 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7055 if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7056 // in sRGB fallback, behave similar to true sRGB: convert this
7057 // value from linear to sRGB
7058 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7060 R_RenderView_UpdateViewVectors();
7062 R_Shadow_UpdateWorldLightSelection();
7064 R_Bloom_StartFrame();
7066 // apply bloom brightness offset
7067 if(r_fb.bloomtexture[0])
7068 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7070 R_Water_StartFrame();
7072 // now we probably have an fbo to render into
7074 depthtexture = r_fb.depthtexture;
7075 colortexture = r_fb.colortexture;
7078 if (r_timereport_active)
7079 R_TimeReport("viewsetup");
7081 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7083 if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7085 R_ClearScreen(r_refdef.fogenabled);
7086 if (r_timereport_active)
7087 R_TimeReport("viewclear");
7089 r_refdef.view.clear = true;
7091 r_refdef.view.showdebug = true;
7094 if (r_timereport_active)
7095 R_TimeReport("visibility");
7097 R_AnimCache_CacheVisibleEntities();
7098 if (r_timereport_active)
7099 R_TimeReport("animcache");
7101 R_Shadow_UpdateBounceGridTexture();
7102 if (r_timereport_active && r_shadow_bouncegrid.integer)
7103 R_TimeReport("bouncegrid");
7105 r_fb.water.numwaterplanes = 0;
7106 if (r_fb.water.enabled)
7107 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7109 R_RenderScene(fbo, depthtexture, colortexture);
7110 r_fb.water.numwaterplanes = 0;
7112 R_BlendView(fbo, depthtexture, colortexture);
7113 if (r_timereport_active)
7114 R_TimeReport("blendview");
7116 GL_Scissor(0, 0, vid.width, vid.height);
7117 GL_ScissorTest(false);
7119 r_refdef.view.matrix = originalmatrix;
7124 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7126 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7128 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7129 if (r_timereport_active)
7130 R_TimeReport("waterworld");
7133 // don't let sound skip if going slow
7134 if (r_refdef.scene.extraupdate)
7137 R_DrawModelsAddWaterPlanes();
7138 if (r_timereport_active)
7139 R_TimeReport("watermodels");
7141 if (r_fb.water.numwaterplanes)
7143 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7144 if (r_timereport_active)
7145 R_TimeReport("waterscenes");
7149 extern cvar_t cl_locs_show;
7150 static void R_DrawLocs(void);
7151 static void R_DrawEntityBBoxes(void);
7152 static void R_DrawModelDecals(void);
7153 extern cvar_t cl_decals_newsystem;
7154 extern qboolean r_shadow_usingdeferredprepass;
7155 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7157 qboolean shadowmapping = false;
7159 if (r_timereport_active)
7160 R_TimeReport("beginscene");
7162 r_refdef.stats.renders++;
7166 // don't let sound skip if going slow
7167 if (r_refdef.scene.extraupdate)
7170 R_MeshQueue_BeginScene();
7174 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);
7176 if (r_timereport_active)
7177 R_TimeReport("skystartframe");
7179 if (cl.csqc_vidvars.drawworld)
7181 // don't let sound skip if going slow
7182 if (r_refdef.scene.extraupdate)
7185 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7187 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7188 if (r_timereport_active)
7189 R_TimeReport("worldsky");
7192 if (R_DrawBrushModelsSky() && r_timereport_active)
7193 R_TimeReport("bmodelsky");
7195 if (skyrendermasked && skyrenderlater)
7197 // we have to force off the water clipping plane while rendering sky
7198 R_SetupView(false, fbo, depthtexture, colortexture);
7200 R_SetupView(true, fbo, depthtexture, colortexture);
7201 if (r_timereport_active)
7202 R_TimeReport("sky");
7206 R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7207 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7208 R_Shadow_PrepareModelShadows();
7209 if (r_timereport_active)
7210 R_TimeReport("preparelights");
7212 if (R_Shadow_ShadowMappingEnabled())
7213 shadowmapping = true;
7215 if (r_shadow_usingdeferredprepass)
7216 R_Shadow_DrawPrepass();
7218 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7220 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7221 if (r_timereport_active)
7222 R_TimeReport("worlddepth");
7224 if (r_depthfirst.integer >= 2)
7226 R_DrawModelsDepth();
7227 if (r_timereport_active)
7228 R_TimeReport("modeldepth");
7231 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7233 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7234 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7235 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7236 // don't let sound skip if going slow
7237 if (r_refdef.scene.extraupdate)
7241 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7243 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7244 if (r_timereport_active)
7245 R_TimeReport("world");
7248 // don't let sound skip if going slow
7249 if (r_refdef.scene.extraupdate)
7253 if (r_timereport_active)
7254 R_TimeReport("models");
7256 // don't let sound skip if going slow
7257 if (r_refdef.scene.extraupdate)
7260 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7262 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7263 R_DrawModelShadows(fbo, depthtexture, colortexture);
7264 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7265 // don't let sound skip if going slow
7266 if (r_refdef.scene.extraupdate)
7270 if (!r_shadow_usingdeferredprepass)
7272 R_Shadow_DrawLights();
7273 if (r_timereport_active)
7274 R_TimeReport("rtlights");
7277 // don't let sound skip if going slow
7278 if (r_refdef.scene.extraupdate)
7281 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7283 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7284 R_DrawModelShadows(fbo, depthtexture, colortexture);
7285 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7286 // don't let sound skip if going slow
7287 if (r_refdef.scene.extraupdate)
7291 if (cl.csqc_vidvars.drawworld)
7293 if (cl_decals_newsystem.integer)
7295 R_DrawModelDecals();
7296 if (r_timereport_active)
7297 R_TimeReport("modeldecals");
7302 if (r_timereport_active)
7303 R_TimeReport("decals");
7307 if (r_timereport_active)
7308 R_TimeReport("particles");
7311 if (r_timereport_active)
7312 R_TimeReport("explosions");
7314 R_DrawLightningBeams();
7315 if (r_timereport_active)
7316 R_TimeReport("lightning");
7320 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7322 if (r_refdef.view.showdebug)
7324 if (cl_locs_show.integer)
7327 if (r_timereport_active)
7328 R_TimeReport("showlocs");
7331 if (r_drawportals.integer)
7334 if (r_timereport_active)
7335 R_TimeReport("portals");
7338 if (r_showbboxes.value > 0)
7340 R_DrawEntityBBoxes();
7341 if (r_timereport_active)
7342 R_TimeReport("bboxes");
7346 if (r_transparent.integer)
7348 R_MeshQueue_RenderTransparent();
7349 if (r_timereport_active)
7350 R_TimeReport("drawtrans");
7353 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))
7355 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7356 if (r_timereport_active)
7357 R_TimeReport("worlddebug");
7358 R_DrawModelsDebug();
7359 if (r_timereport_active)
7360 R_TimeReport("modeldebug");
7363 if (cl.csqc_vidvars.drawworld)
7365 R_Shadow_DrawCoronas();
7366 if (r_timereport_active)
7367 R_TimeReport("coronas");
7372 GL_DepthTest(false);
7373 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7374 GL_Color(1, 1, 1, 1);
7375 qglBegin(GL_POLYGON);
7376 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7377 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7378 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7379 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7381 qglBegin(GL_POLYGON);
7382 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]);
7383 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]);
7384 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]);
7385 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]);
7387 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7391 // don't let sound skip if going slow
7392 if (r_refdef.scene.extraupdate)
7396 static const unsigned short bboxelements[36] =
7406 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7409 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7411 RSurf_ActiveWorldEntity();
7413 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7414 GL_DepthMask(false);
7415 GL_DepthRange(0, 1);
7416 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7417 // R_Mesh_ResetTextureState();
7419 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7420 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7421 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7422 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7423 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7424 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7425 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7426 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7427 R_FillColors(color4f, 8, cr, cg, cb, ca);
7428 if (r_refdef.fogenabled)
7430 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7432 f1 = RSurf_FogVertex(v);
7434 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7435 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7436 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7439 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7440 R_Mesh_ResetTextureState();
7441 R_SetupShader_Generic_NoTexture(false, false);
7442 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7445 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7447 prvm_prog_t *prog = SVVM_prog;
7450 prvm_edict_t *edict;
7452 // this function draws bounding boxes of server entities
7456 GL_CullFace(GL_NONE);
7457 R_SetupShader_Generic_NoTexture(false, false);
7459 for (i = 0;i < numsurfaces;i++)
7461 edict = PRVM_EDICT_NUM(surfacelist[i]);
7462 switch ((int)PRVM_serveredictfloat(edict, solid))
7464 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7465 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7466 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7467 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7468 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7469 case SOLID_CORPSE: Vector4Set(color, 1, 0.5, 0, 0.05);break;
7470 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7472 color[3] *= r_showbboxes.value;
7473 color[3] = bound(0, color[3], 1);
7474 GL_DepthTest(!r_showdisabledepthtest.integer);
7475 GL_CullFace(r_refdef.view.cullface_front);
7476 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7480 static void R_DrawEntityBBoxes(void)
7483 prvm_edict_t *edict;
7485 prvm_prog_t *prog = SVVM_prog;
7487 // this function draws bounding boxes of server entities
7491 for (i = 0;i < prog->num_edicts;i++)
7493 edict = PRVM_EDICT_NUM(i);
7494 if (edict->priv.server->free)
7496 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7497 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7499 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7501 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7502 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7506 static const int nomodelelement3i[24] =
7518 static const unsigned short nomodelelement3s[24] =
7530 static const float nomodelvertex3f[6*3] =
7540 static const float nomodelcolor4f[6*4] =
7542 0.0f, 0.0f, 0.5f, 1.0f,
7543 0.0f, 0.0f, 0.5f, 1.0f,
7544 0.0f, 0.5f, 0.0f, 1.0f,
7545 0.0f, 0.5f, 0.0f, 1.0f,
7546 0.5f, 0.0f, 0.0f, 1.0f,
7547 0.5f, 0.0f, 0.0f, 1.0f
7550 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7556 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);
7558 // this is only called once per entity so numsurfaces is always 1, and
7559 // surfacelist is always {0}, so this code does not handle batches
7561 if (rsurface.ent_flags & RENDER_ADDITIVE)
7563 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7564 GL_DepthMask(false);
7566 else if (rsurface.colormod[3] < 1)
7568 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7569 GL_DepthMask(false);
7573 GL_BlendFunc(GL_ONE, GL_ZERO);
7576 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7577 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7578 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7579 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7580 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7581 for (i = 0, c = color4f;i < 6;i++, c += 4)
7583 c[0] *= rsurface.colormod[0];
7584 c[1] *= rsurface.colormod[1];
7585 c[2] *= rsurface.colormod[2];
7586 c[3] *= rsurface.colormod[3];
7588 if (r_refdef.fogenabled)
7590 for (i = 0, c = color4f;i < 6;i++, c += 4)
7592 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7594 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7595 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7596 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7599 // R_Mesh_ResetTextureState();
7600 R_SetupShader_Generic_NoTexture(false, false);
7601 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7602 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7605 void R_DrawNoModel(entity_render_t *ent)
7608 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7609 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7610 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7612 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7615 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7617 vec3_t right1, right2, diff, normal;
7619 VectorSubtract (org2, org1, normal);
7621 // calculate 'right' vector for start
7622 VectorSubtract (r_refdef.view.origin, org1, diff);
7623 CrossProduct (normal, diff, right1);
7624 VectorNormalize (right1);
7626 // calculate 'right' vector for end
7627 VectorSubtract (r_refdef.view.origin, org2, diff);
7628 CrossProduct (normal, diff, right2);
7629 VectorNormalize (right2);
7631 vert[ 0] = org1[0] + width * right1[0];
7632 vert[ 1] = org1[1] + width * right1[1];
7633 vert[ 2] = org1[2] + width * right1[2];
7634 vert[ 3] = org1[0] - width * right1[0];
7635 vert[ 4] = org1[1] - width * right1[1];
7636 vert[ 5] = org1[2] - width * right1[2];
7637 vert[ 6] = org2[0] - width * right2[0];
7638 vert[ 7] = org2[1] - width * right2[1];
7639 vert[ 8] = org2[2] - width * right2[2];
7640 vert[ 9] = org2[0] + width * right2[0];
7641 vert[10] = org2[1] + width * right2[1];
7642 vert[11] = org2[2] + width * right2[2];
7645 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)
7647 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7648 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7649 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7650 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7651 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7652 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7653 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7654 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7655 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7656 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7657 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7658 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7661 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7666 VectorSet(v, x, y, z);
7667 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7668 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7670 if (i == mesh->numvertices)
7672 if (mesh->numvertices < mesh->maxvertices)
7674 VectorCopy(v, vertex3f);
7675 mesh->numvertices++;
7677 return mesh->numvertices;
7683 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7687 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7688 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7689 e = mesh->element3i + mesh->numtriangles * 3;
7690 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7692 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7693 if (mesh->numtriangles < mesh->maxtriangles)
7698 mesh->numtriangles++;
7700 element[1] = element[2];
7704 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7708 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7709 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7710 e = mesh->element3i + mesh->numtriangles * 3;
7711 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7713 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7714 if (mesh->numtriangles < mesh->maxtriangles)
7719 mesh->numtriangles++;
7721 element[1] = element[2];
7725 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7726 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7728 int planenum, planenum2;
7731 mplane_t *plane, *plane2;
7733 double temppoints[2][256*3];
7734 // figure out how large a bounding box we need to properly compute this brush
7736 for (w = 0;w < numplanes;w++)
7737 maxdist = max(maxdist, fabs(planes[w].dist));
7738 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7739 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7740 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7744 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7745 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7747 if (planenum2 == planenum)
7749 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);
7752 if (tempnumpoints < 3)
7754 // generate elements forming a triangle fan for this polygon
7755 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7759 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)
7761 texturelayer_t *layer;
7762 layer = t->currentlayers + t->currentnumlayers++;
7764 layer->depthmask = depthmask;
7765 layer->blendfunc1 = blendfunc1;
7766 layer->blendfunc2 = blendfunc2;
7767 layer->texture = texture;
7768 layer->texmatrix = *matrix;
7769 layer->color[0] = r;
7770 layer->color[1] = g;
7771 layer->color[2] = b;
7772 layer->color[3] = a;
7775 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7777 if(parms[0] == 0 && parms[1] == 0)
7779 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7780 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7785 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7788 index = parms[2] + rsurface.shadertime * parms[3];
7789 index -= floor(index);
7790 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7793 case Q3WAVEFUNC_NONE:
7794 case Q3WAVEFUNC_NOISE:
7795 case Q3WAVEFUNC_COUNT:
7798 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7799 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7800 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7801 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7802 case Q3WAVEFUNC_TRIANGLE:
7804 f = index - floor(index);
7817 f = parms[0] + parms[1] * f;
7818 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7819 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7823 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7829 matrix4x4_t matrix, temp;
7830 switch(tcmod->tcmod)
7834 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7835 matrix = r_waterscrollmatrix;
7837 matrix = identitymatrix;
7839 case Q3TCMOD_ENTITYTRANSLATE:
7840 // this is used in Q3 to allow the gamecode to control texcoord
7841 // scrolling on the entity, which is not supported in darkplaces yet.
7842 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7844 case Q3TCMOD_ROTATE:
7845 f = tcmod->parms[0] * rsurface.shadertime;
7846 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7847 Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
7848 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7851 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7853 case Q3TCMOD_SCROLL:
7854 // extra care is needed because of precision breakdown with large values of time
7855 offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7856 offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7857 Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7859 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7860 w = (int) tcmod->parms[0];
7861 h = (int) tcmod->parms[1];
7862 f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7864 idx = (int) floor(f * w * h);
7865 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7867 case Q3TCMOD_STRETCH:
7868 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7869 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7871 case Q3TCMOD_TRANSFORM:
7872 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7873 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7874 VectorSet(tcmat + 6, 0 , 0 , 1);
7875 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7876 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7878 case Q3TCMOD_TURBULENT:
7879 // this is handled in the RSurf_PrepareVertices function
7880 matrix = identitymatrix;
7884 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7887 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7889 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7890 char name[MAX_QPATH];
7891 skinframe_t *skinframe;
7892 unsigned char pixels[296*194];
7893 strlcpy(cache->name, skinname, sizeof(cache->name));
7894 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7895 if (developer_loading.integer)
7896 Con_Printf("loading %s\n", name);
7897 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7898 if (!skinframe || !skinframe->base)
7901 fs_offset_t filesize;
7903 f = FS_LoadFile(name, tempmempool, true, &filesize);
7906 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7907 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7911 cache->skinframe = skinframe;
7914 texture_t *R_GetCurrentTexture(texture_t *t)
7917 const entity_render_t *ent = rsurface.entity;
7918 dp_model_t *model = ent->model; // when calling this, ent must not be NULL
7919 q3shaderinfo_layer_tcmod_t *tcmod;
7921 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
7922 return t->currentframe;
7923 t->update_lastrenderframe = r_textureframe;
7924 t->update_lastrenderentity = (void *)ent;
7926 if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7927 t->camera_entity = ent->entitynumber;
7929 t->camera_entity = 0;
7931 // switch to an alternate material if this is a q1bsp animated material
7933 texture_t *texture = t;
7934 int s = rsurface.ent_skinnum;
7935 if ((unsigned int)s >= (unsigned int)model->numskins)
7937 if (model->skinscenes)
7939 if (model->skinscenes[s].framecount > 1)
7940 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7942 s = model->skinscenes[s].firstframe;
7945 t = t + s * model->num_surfaces;
7948 // use an alternate animation if the entity's frame is not 0,
7949 // and only if the texture has an alternate animation
7950 if (rsurface.ent_alttextures && t->anim_total[1])
7951 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7953 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7955 texture->currentframe = t;
7958 // update currentskinframe to be a qw skin or animation frame
7959 if (rsurface.ent_qwskin >= 0)
7961 i = rsurface.ent_qwskin;
7962 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7964 r_qwskincache_size = cl.maxclients;
7966 Mem_Free(r_qwskincache);
7967 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7969 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7970 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7971 t->currentskinframe = r_qwskincache[i].skinframe;
7972 if (t->currentskinframe == NULL)
7973 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7975 else if (t->numskinframes >= 2)
7976 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7977 if (t->backgroundnumskinframes >= 2)
7978 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7980 t->currentmaterialflags = t->basematerialflags;
7981 t->currentalpha = rsurface.colormod[3];
7982 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7983 t->currentalpha *= r_wateralpha.value;
7984 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
7985 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7986 if(!r_fb.water.enabled || r_refdef.view.isoverlay)
7987 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7988 if (!(rsurface.ent_flags & RENDER_LIGHT))
7989 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7990 else if (FAKELIGHT_ENABLED)
7992 // no modellight if using fakelight for the map
7994 else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7996 // pick a model lighting mode
7997 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7998 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8000 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8002 if (rsurface.ent_flags & RENDER_ADDITIVE)
8003 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8004 else if (t->currentalpha < 1)
8005 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8006 // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8007 if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8008 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8009 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8010 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8011 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8012 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8013 if (t->backgroundnumskinframes)
8014 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8015 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8017 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8018 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8021 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8022 if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8024 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8025 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8027 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8028 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8030 // there is no tcmod
8031 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8033 t->currenttexmatrix = r_waterscrollmatrix;
8034 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8036 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8038 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8039 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8042 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8043 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8044 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8045 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8047 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8048 if (t->currentskinframe->qpixels)
8049 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8050 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8051 if (!t->basetexture)
8052 t->basetexture = r_texture_notexture;
8053 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8054 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8055 t->nmaptexture = t->currentskinframe->nmap;
8056 if (!t->nmaptexture)
8057 t->nmaptexture = r_texture_blanknormalmap;
8058 t->glosstexture = r_texture_black;
8059 t->glowtexture = t->currentskinframe->glow;
8060 t->fogtexture = t->currentskinframe->fog;
8061 t->reflectmasktexture = t->currentskinframe->reflect;
8062 if (t->backgroundnumskinframes)
8064 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8065 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8066 t->backgroundglosstexture = r_texture_black;
8067 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8068 if (!t->backgroundnmaptexture)
8069 t->backgroundnmaptexture = r_texture_blanknormalmap;
8070 // make sure that if glow is going to be used, both textures are not NULL
8071 if (!t->backgroundglowtexture && t->glowtexture)
8072 t->backgroundglowtexture = r_texture_black;
8073 if (!t->glowtexture && t->backgroundglowtexture)
8074 t->glowtexture = r_texture_black;
8078 t->backgroundbasetexture = r_texture_white;
8079 t->backgroundnmaptexture = r_texture_blanknormalmap;
8080 t->backgroundglosstexture = r_texture_black;
8081 t->backgroundglowtexture = NULL;
8083 t->specularpower = r_shadow_glossexponent.value;
8084 // TODO: store reference values for these in the texture?
8085 t->specularscale = 0;
8086 if (r_shadow_gloss.integer > 0)
8088 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8090 if (r_shadow_glossintensity.value > 0)
8092 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8093 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8094 t->specularscale = r_shadow_glossintensity.value;
8097 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8099 t->glosstexture = r_texture_white;
8100 t->backgroundglosstexture = r_texture_white;
8101 t->specularscale = r_shadow_gloss2intensity.value;
8102 t->specularpower = r_shadow_gloss2exponent.value;
8105 t->specularscale *= t->specularscalemod;
8106 t->specularpower *= t->specularpowermod;
8107 t->rtlightambient = 0;
8109 // lightmaps mode looks bad with dlights using actual texturing, so turn
8110 // off the colormap and glossmap, but leave the normalmap on as it still
8111 // accurately represents the shading involved
8112 if (gl_lightmaps.integer)
8114 t->basetexture = r_texture_grey128;
8115 t->pantstexture = r_texture_black;
8116 t->shirttexture = r_texture_black;
8117 if (gl_lightmaps.integer < 2)
8118 t->nmaptexture = r_texture_blanknormalmap;
8119 t->glosstexture = r_texture_black;
8120 t->glowtexture = NULL;
8121 t->fogtexture = NULL;
8122 t->reflectmasktexture = NULL;
8123 t->backgroundbasetexture = NULL;
8124 if (gl_lightmaps.integer < 2)
8125 t->backgroundnmaptexture = r_texture_blanknormalmap;
8126 t->backgroundglosstexture = r_texture_black;
8127 t->backgroundglowtexture = NULL;
8128 t->specularscale = 0;
8129 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8132 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8133 VectorClear(t->dlightcolor);
8134 t->currentnumlayers = 0;
8135 if (t->currentmaterialflags & MATERIALFLAG_WALL)
8137 int blendfunc1, blendfunc2;
8139 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8141 blendfunc1 = GL_SRC_ALPHA;
8142 blendfunc2 = GL_ONE;
8144 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8146 blendfunc1 = GL_SRC_ALPHA;
8147 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8149 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8151 blendfunc1 = t->customblendfunc[0];
8152 blendfunc2 = t->customblendfunc[1];
8156 blendfunc1 = GL_ONE;
8157 blendfunc2 = GL_ZERO;
8159 // don't colormod evilblend textures
8160 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8161 VectorSet(t->lightmapcolor, 1, 1, 1);
8162 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8163 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8165 // fullbright is not affected by r_refdef.lightmapintensity
8166 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]);
8167 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8168 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]);
8169 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8170 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]);
8174 vec3_t ambientcolor;
8176 // set the color tint used for lights affecting this surface
8177 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8179 // q3bsp has no lightmap updates, so the lightstylevalue that
8180 // would normally be baked into the lightmap must be
8181 // applied to the color
8182 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8183 if (model->type == mod_brushq3)
8184 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8185 colorscale *= r_refdef.lightmapintensity;
8186 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8187 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8188 // basic lit geometry
8189 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]);
8190 // add pants/shirt if needed
8191 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8192 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]);
8193 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8194 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]);
8195 // now add ambient passes if needed
8196 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8198 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]);
8199 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8200 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]);
8201 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8202 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]);
8205 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8206 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]);
8207 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8209 // if this is opaque use alpha blend which will darken the earlier
8212 // if this is an alpha blended material, all the earlier passes
8213 // were darkened by fog already, so we only need to add the fog
8214 // color ontop through the fog mask texture
8216 // if this is an additive blended material, all the earlier passes
8217 // were darkened by fog already, and we should not add fog color
8218 // (because the background was not darkened, there is no fog color
8219 // that was lost behind it).
8220 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]);
8224 return t->currentframe;
8227 rsurfacestate_t rsurface;
8229 void RSurf_ActiveWorldEntity(void)
8231 dp_model_t *model = r_refdef.scene.worldmodel;
8232 //if (rsurface.entity == r_refdef.scene.worldentity)
8234 rsurface.entity = r_refdef.scene.worldentity;
8235 rsurface.skeleton = NULL;
8236 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8237 rsurface.ent_skinnum = 0;
8238 rsurface.ent_qwskin = -1;
8239 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8240 rsurface.shadertime = r_refdef.scene.time;
8241 rsurface.matrix = identitymatrix;
8242 rsurface.inversematrix = identitymatrix;
8243 rsurface.matrixscale = 1;
8244 rsurface.inversematrixscale = 1;
8245 R_EntityMatrix(&identitymatrix);
8246 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8247 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8248 rsurface.fograngerecip = r_refdef.fograngerecip;
8249 rsurface.fogheightfade = r_refdef.fogheightfade;
8250 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8251 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8252 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8253 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8254 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8255 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8256 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8257 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8258 rsurface.colormod[3] = 1;
8259 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);
8260 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8261 rsurface.frameblend[0].lerp = 1;
8262 rsurface.ent_alttextures = false;
8263 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8264 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8265 rsurface.entityskeletaltransform3x4 = NULL;
8266 rsurface.entityskeletalnumtransforms = 0;
8267 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8268 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8269 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8270 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8271 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8272 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8273 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8274 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8275 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8276 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8277 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8278 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8279 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8280 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8281 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8282 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8283 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8284 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8285 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8286 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8287 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8288 rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8289 rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8290 rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8291 rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8292 rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8293 rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8294 rsurface.modelelement3i = model->surfmesh.data_element3i;
8295 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8296 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8297 rsurface.modelelement3s = model->surfmesh.data_element3s;
8298 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8299 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8300 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8301 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8302 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8303 rsurface.modelsurfaces = model->data_surfaces;
8304 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8305 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8306 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8307 rsurface.modelgeneratedvertex = false;
8308 rsurface.batchgeneratedvertex = false;
8309 rsurface.batchfirstvertex = 0;
8310 rsurface.batchnumvertices = 0;
8311 rsurface.batchfirsttriangle = 0;
8312 rsurface.batchnumtriangles = 0;
8313 rsurface.batchvertex3f = NULL;
8314 rsurface.batchvertex3f_vertexbuffer = NULL;
8315 rsurface.batchvertex3f_bufferoffset = 0;
8316 rsurface.batchsvector3f = NULL;
8317 rsurface.batchsvector3f_vertexbuffer = NULL;
8318 rsurface.batchsvector3f_bufferoffset = 0;
8319 rsurface.batchtvector3f = NULL;
8320 rsurface.batchtvector3f_vertexbuffer = NULL;
8321 rsurface.batchtvector3f_bufferoffset = 0;
8322 rsurface.batchnormal3f = NULL;
8323 rsurface.batchnormal3f_vertexbuffer = NULL;
8324 rsurface.batchnormal3f_bufferoffset = 0;
8325 rsurface.batchlightmapcolor4f = NULL;
8326 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8327 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8328 rsurface.batchtexcoordtexture2f = NULL;
8329 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8330 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8331 rsurface.batchtexcoordlightmap2f = NULL;
8332 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8333 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8334 rsurface.batchskeletalindex4ub = NULL;
8335 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8336 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8337 rsurface.batchskeletalweight4ub = NULL;
8338 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8339 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8340 rsurface.batchvertexmesh = NULL;
8341 rsurface.batchvertexmeshbuffer = NULL;
8342 rsurface.batchvertex3fbuffer = NULL;
8343 rsurface.batchelement3i = NULL;
8344 rsurface.batchelement3i_indexbuffer = NULL;
8345 rsurface.batchelement3i_bufferoffset = 0;
8346 rsurface.batchelement3s = NULL;
8347 rsurface.batchelement3s_indexbuffer = NULL;
8348 rsurface.batchelement3s_bufferoffset = 0;
8349 rsurface.passcolor4f = NULL;
8350 rsurface.passcolor4f_vertexbuffer = NULL;
8351 rsurface.passcolor4f_bufferoffset = 0;
8352 rsurface.forcecurrenttextureupdate = false;
8355 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8357 dp_model_t *model = ent->model;
8358 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8360 rsurface.entity = (entity_render_t *)ent;
8361 rsurface.skeleton = ent->skeleton;
8362 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8363 rsurface.ent_skinnum = ent->skinnum;
8364 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;
8365 rsurface.ent_flags = ent->flags;
8366 rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8367 rsurface.matrix = ent->matrix;
8368 rsurface.inversematrix = ent->inversematrix;
8369 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8370 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8371 R_EntityMatrix(&rsurface.matrix);
8372 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8373 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8374 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8375 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8376 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8377 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8378 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8379 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8380 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8381 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8382 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8383 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8384 rsurface.colormod[3] = ent->alpha;
8385 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8386 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8387 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8388 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8389 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8390 if (ent->model->brush.submodel && !prepass)
8392 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8393 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8395 // if the animcache code decided it should use the shader path, skip the deform step
8396 rsurface.entityskeletaltransform3x4 = ent->animcache_vertex3f ? NULL : ent->animcache_skeletaltransform3x4;
8397 rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8398 if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8400 if (ent->animcache_vertex3f)
8402 rsurface.modelvertex3f = ent->animcache_vertex3f;
8403 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8404 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8405 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8406 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8407 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8408 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8410 else if (wanttangents)
8412 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8413 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8414 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8415 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8416 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8417 rsurface.modelvertexmesh = NULL;
8418 rsurface.modelvertexmeshbuffer = NULL;
8419 rsurface.modelvertex3fbuffer = NULL;
8421 else if (wantnormals)
8423 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8424 rsurface.modelsvector3f = NULL;
8425 rsurface.modeltvector3f = NULL;
8426 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8427 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8428 rsurface.modelvertexmesh = NULL;
8429 rsurface.modelvertexmeshbuffer = NULL;
8430 rsurface.modelvertex3fbuffer = NULL;
8434 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8435 rsurface.modelsvector3f = NULL;
8436 rsurface.modeltvector3f = NULL;
8437 rsurface.modelnormal3f = NULL;
8438 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8439 rsurface.modelvertexmesh = NULL;
8440 rsurface.modelvertexmeshbuffer = NULL;
8441 rsurface.modelvertex3fbuffer = NULL;
8443 rsurface.modelvertex3f_vertexbuffer = 0;
8444 rsurface.modelvertex3f_bufferoffset = 0;
8445 rsurface.modelsvector3f_vertexbuffer = 0;
8446 rsurface.modelsvector3f_bufferoffset = 0;
8447 rsurface.modeltvector3f_vertexbuffer = 0;
8448 rsurface.modeltvector3f_bufferoffset = 0;
8449 rsurface.modelnormal3f_vertexbuffer = 0;
8450 rsurface.modelnormal3f_bufferoffset = 0;
8451 rsurface.modelgeneratedvertex = true;
8455 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8456 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8457 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8458 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8459 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8460 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8461 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8462 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8463 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8464 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8465 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8466 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8467 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8468 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8469 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8470 rsurface.modelgeneratedvertex = false;
8472 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8473 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8474 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8475 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8476 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8477 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8478 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8479 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8480 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8481 rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8482 rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8483 rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8484 rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8485 rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8486 rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8487 rsurface.modelelement3i = model->surfmesh.data_element3i;
8488 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8489 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8490 rsurface.modelelement3s = model->surfmesh.data_element3s;
8491 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8492 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8493 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8494 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8495 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8496 rsurface.modelsurfaces = model->data_surfaces;
8497 rsurface.batchgeneratedvertex = false;
8498 rsurface.batchfirstvertex = 0;
8499 rsurface.batchnumvertices = 0;
8500 rsurface.batchfirsttriangle = 0;
8501 rsurface.batchnumtriangles = 0;
8502 rsurface.batchvertex3f = NULL;
8503 rsurface.batchvertex3f_vertexbuffer = NULL;
8504 rsurface.batchvertex3f_bufferoffset = 0;
8505 rsurface.batchsvector3f = NULL;
8506 rsurface.batchsvector3f_vertexbuffer = NULL;
8507 rsurface.batchsvector3f_bufferoffset = 0;
8508 rsurface.batchtvector3f = NULL;
8509 rsurface.batchtvector3f_vertexbuffer = NULL;
8510 rsurface.batchtvector3f_bufferoffset = 0;
8511 rsurface.batchnormal3f = NULL;
8512 rsurface.batchnormal3f_vertexbuffer = NULL;
8513 rsurface.batchnormal3f_bufferoffset = 0;
8514 rsurface.batchlightmapcolor4f = NULL;
8515 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8516 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8517 rsurface.batchtexcoordtexture2f = NULL;
8518 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8519 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8520 rsurface.batchtexcoordlightmap2f = NULL;
8521 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8522 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8523 rsurface.batchskeletalindex4ub = NULL;
8524 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8525 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8526 rsurface.batchskeletalweight4ub = NULL;
8527 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8528 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8529 rsurface.batchvertexmesh = NULL;
8530 rsurface.batchvertexmeshbuffer = NULL;
8531 rsurface.batchvertex3fbuffer = NULL;
8532 rsurface.batchelement3i = NULL;
8533 rsurface.batchelement3i_indexbuffer = NULL;
8534 rsurface.batchelement3i_bufferoffset = 0;
8535 rsurface.batchelement3s = NULL;
8536 rsurface.batchelement3s_indexbuffer = NULL;
8537 rsurface.batchelement3s_bufferoffset = 0;
8538 rsurface.passcolor4f = NULL;
8539 rsurface.passcolor4f_vertexbuffer = NULL;
8540 rsurface.passcolor4f_bufferoffset = 0;
8541 rsurface.forcecurrenttextureupdate = false;
8544 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)
8546 rsurface.entity = r_refdef.scene.worldentity;
8547 rsurface.skeleton = NULL;
8548 rsurface.ent_skinnum = 0;
8549 rsurface.ent_qwskin = -1;
8550 rsurface.ent_flags = entflags;
8551 rsurface.shadertime = r_refdef.scene.time - shadertime;
8552 rsurface.modelnumvertices = numvertices;
8553 rsurface.modelnumtriangles = numtriangles;
8554 rsurface.matrix = *matrix;
8555 rsurface.inversematrix = *inversematrix;
8556 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8557 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8558 R_EntityMatrix(&rsurface.matrix);
8559 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8560 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8561 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8562 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8563 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8564 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8565 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8566 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8567 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8568 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8569 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8570 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8571 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);
8572 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8573 rsurface.frameblend[0].lerp = 1;
8574 rsurface.ent_alttextures = false;
8575 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8576 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8577 rsurface.entityskeletaltransform3x4 = NULL;
8578 rsurface.entityskeletalnumtransforms = 0;
8581 rsurface.modelvertex3f = (float *)vertex3f;
8582 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8583 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8584 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8586 else if (wantnormals)
8588 rsurface.modelvertex3f = (float *)vertex3f;
8589 rsurface.modelsvector3f = NULL;
8590 rsurface.modeltvector3f = NULL;
8591 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8595 rsurface.modelvertex3f = (float *)vertex3f;
8596 rsurface.modelsvector3f = NULL;
8597 rsurface.modeltvector3f = NULL;
8598 rsurface.modelnormal3f = NULL;
8600 rsurface.modelvertexmesh = NULL;
8601 rsurface.modelvertexmeshbuffer = NULL;
8602 rsurface.modelvertex3fbuffer = NULL;
8603 rsurface.modelvertex3f_vertexbuffer = 0;
8604 rsurface.modelvertex3f_bufferoffset = 0;
8605 rsurface.modelsvector3f_vertexbuffer = 0;
8606 rsurface.modelsvector3f_bufferoffset = 0;
8607 rsurface.modeltvector3f_vertexbuffer = 0;
8608 rsurface.modeltvector3f_bufferoffset = 0;
8609 rsurface.modelnormal3f_vertexbuffer = 0;
8610 rsurface.modelnormal3f_bufferoffset = 0;
8611 rsurface.modelgeneratedvertex = true;
8612 rsurface.modellightmapcolor4f = (float *)color4f;
8613 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8614 rsurface.modellightmapcolor4f_bufferoffset = 0;
8615 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8616 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8617 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8618 rsurface.modeltexcoordlightmap2f = NULL;
8619 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8620 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8621 rsurface.modelskeletalindex4ub = NULL;
8622 rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8623 rsurface.modelskeletalindex4ub_bufferoffset = 0;
8624 rsurface.modelskeletalweight4ub = NULL;
8625 rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8626 rsurface.modelskeletalweight4ub_bufferoffset = 0;
8627 rsurface.modelelement3i = (int *)element3i;
8628 rsurface.modelelement3i_indexbuffer = NULL;
8629 rsurface.modelelement3i_bufferoffset = 0;
8630 rsurface.modelelement3s = (unsigned short *)element3s;
8631 rsurface.modelelement3s_indexbuffer = NULL;
8632 rsurface.modelelement3s_bufferoffset = 0;
8633 rsurface.modellightmapoffsets = NULL;
8634 rsurface.modelsurfaces = NULL;
8635 rsurface.batchgeneratedvertex = false;
8636 rsurface.batchfirstvertex = 0;
8637 rsurface.batchnumvertices = 0;
8638 rsurface.batchfirsttriangle = 0;
8639 rsurface.batchnumtriangles = 0;
8640 rsurface.batchvertex3f = NULL;
8641 rsurface.batchvertex3f_vertexbuffer = NULL;
8642 rsurface.batchvertex3f_bufferoffset = 0;
8643 rsurface.batchsvector3f = NULL;
8644 rsurface.batchsvector3f_vertexbuffer = NULL;
8645 rsurface.batchsvector3f_bufferoffset = 0;
8646 rsurface.batchtvector3f = NULL;
8647 rsurface.batchtvector3f_vertexbuffer = NULL;
8648 rsurface.batchtvector3f_bufferoffset = 0;
8649 rsurface.batchnormal3f = NULL;
8650 rsurface.batchnormal3f_vertexbuffer = NULL;
8651 rsurface.batchnormal3f_bufferoffset = 0;
8652 rsurface.batchlightmapcolor4f = NULL;
8653 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8654 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8655 rsurface.batchtexcoordtexture2f = NULL;
8656 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8657 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8658 rsurface.batchtexcoordlightmap2f = NULL;
8659 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8660 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8661 rsurface.batchskeletalindex4ub = NULL;
8662 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8663 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8664 rsurface.batchskeletalweight4ub = NULL;
8665 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8666 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8667 rsurface.batchvertexmesh = NULL;
8668 rsurface.batchvertexmeshbuffer = NULL;
8669 rsurface.batchvertex3fbuffer = NULL;
8670 rsurface.batchelement3i = NULL;
8671 rsurface.batchelement3i_indexbuffer = NULL;
8672 rsurface.batchelement3i_bufferoffset = 0;
8673 rsurface.batchelement3s = NULL;
8674 rsurface.batchelement3s_indexbuffer = NULL;
8675 rsurface.batchelement3s_bufferoffset = 0;
8676 rsurface.passcolor4f = NULL;
8677 rsurface.passcolor4f_vertexbuffer = NULL;
8678 rsurface.passcolor4f_bufferoffset = 0;
8679 rsurface.forcecurrenttextureupdate = true;
8681 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8683 if ((wantnormals || wanttangents) && !normal3f)
8685 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8686 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8688 if (wanttangents && !svector3f)
8690 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8691 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8692 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8697 float RSurf_FogPoint(const float *v)
8699 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8700 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8701 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8702 float FogHeightFade = r_refdef.fogheightfade;
8704 unsigned int fogmasktableindex;
8705 if (r_refdef.fogplaneviewabove)
8706 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8708 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8709 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8710 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8713 float RSurf_FogVertex(const float *v)
8715 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8716 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8717 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8718 float FogHeightFade = rsurface.fogheightfade;
8720 unsigned int fogmasktableindex;
8721 if (r_refdef.fogplaneviewabove)
8722 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8724 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8725 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8726 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8729 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8732 for (i = 0;i < numelements;i++)
8733 outelement3i[i] = inelement3i[i] + adjust;
8736 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8737 extern cvar_t gl_vbo;
8738 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8746 int surfacefirsttriangle;
8747 int surfacenumtriangles;
8748 int surfacefirstvertex;
8749 int surfaceendvertex;
8750 int surfacenumvertices;
8751 int batchnumvertices;
8752 int batchnumtriangles;
8756 qboolean dynamicvertex;
8760 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8763 q3shaderinfo_deform_t *deform;
8764 const msurface_t *surface, *firstsurface;
8765 r_vertexmesh_t *vertexmesh;
8766 if (!texturenumsurfaces)
8768 // find vertex range of this surface batch
8770 firstsurface = texturesurfacelist[0];
8771 firsttriangle = firstsurface->num_firsttriangle;
8772 batchnumvertices = 0;
8773 batchnumtriangles = 0;
8774 firstvertex = endvertex = firstsurface->num_firstvertex;
8775 for (i = 0;i < texturenumsurfaces;i++)
8777 surface = texturesurfacelist[i];
8778 if (surface != firstsurface + i)
8780 surfacefirstvertex = surface->num_firstvertex;
8781 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8782 surfacenumvertices = surface->num_vertices;
8783 surfacenumtriangles = surface->num_triangles;
8784 if (firstvertex > surfacefirstvertex)
8785 firstvertex = surfacefirstvertex;
8786 if (endvertex < surfaceendvertex)
8787 endvertex = surfaceendvertex;
8788 batchnumvertices += surfacenumvertices;
8789 batchnumtriangles += surfacenumtriangles;
8792 // we now know the vertex range used, and if there are any gaps in it
8793 rsurface.batchfirstvertex = firstvertex;
8794 rsurface.batchnumvertices = endvertex - firstvertex;
8795 rsurface.batchfirsttriangle = firsttriangle;
8796 rsurface.batchnumtriangles = batchnumtriangles;
8798 // this variable holds flags for which properties have been updated that
8799 // may require regenerating vertexmesh array...
8802 // check if any dynamic vertex processing must occur
8803 dynamicvertex = false;
8805 // a cvar to force the dynamic vertex path to be taken, for debugging
8806 if (r_batch_debugdynamicvertexpath.integer)
8807 dynamicvertex = true;
8809 // if there is a chance of animated vertex colors, it's a dynamic batch
8810 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8812 dynamicvertex = true;
8813 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8816 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8818 switch (deform->deform)
8821 case Q3DEFORM_PROJECTIONSHADOW:
8822 case Q3DEFORM_TEXT0:
8823 case Q3DEFORM_TEXT1:
8824 case Q3DEFORM_TEXT2:
8825 case Q3DEFORM_TEXT3:
8826 case Q3DEFORM_TEXT4:
8827 case Q3DEFORM_TEXT5:
8828 case Q3DEFORM_TEXT6:
8829 case Q3DEFORM_TEXT7:
8832 case Q3DEFORM_AUTOSPRITE:
8833 dynamicvertex = true;
8834 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
8835 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8837 case Q3DEFORM_AUTOSPRITE2:
8838 dynamicvertex = true;
8839 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
8840 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8842 case Q3DEFORM_NORMAL:
8843 dynamicvertex = true;
8844 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
8845 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8848 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8849 break; // if wavefunc is a nop, ignore this transform
8850 dynamicvertex = true;
8851 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
8852 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8854 case Q3DEFORM_BULGE:
8855 dynamicvertex = true;
8856 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
8857 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8860 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8861 break; // if wavefunc is a nop, ignore this transform
8862 dynamicvertex = true;
8863 batchneed |= BATCHNEED_ARRAY_VERTEX;
8864 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8868 switch(rsurface.texture->tcgen.tcgen)
8871 case Q3TCGEN_TEXTURE:
8873 case Q3TCGEN_LIGHTMAP:
8874 dynamicvertex = true;
8875 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8876 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8878 case Q3TCGEN_VECTOR:
8879 dynamicvertex = true;
8880 batchneed |= BATCHNEED_ARRAY_VERTEX;
8881 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8883 case Q3TCGEN_ENVIRONMENT:
8884 dynamicvertex = true;
8885 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
8886 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8889 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8891 dynamicvertex = true;
8892 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
8893 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8896 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8898 dynamicvertex = true;
8899 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8902 // when the model data has no vertex buffer (dynamic mesh), we need to
8904 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8905 batchneed |= BATCHNEED_NOGAPS;
8907 // the caller can specify BATCHNEED_NOGAPS to force a batch with
8908 // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
8909 // we ensure this by treating the vertex batch as dynamic...
8910 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
8911 dynamicvertex = true;
8915 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8916 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8917 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8918 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8919 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8920 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8921 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8922 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL) batchneed |= BATCHNEED_ARRAY_SKELETAL;
8925 // if needsupdate, we have to do a dynamic vertex batch for sure
8926 if (needsupdate & batchneed)
8927 dynamicvertex = true;
8929 // see if we need to build vertexmesh from arrays
8930 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8931 dynamicvertex = true;
8933 // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
8934 if (dynamicvertex && rsurface.entityskeletaltransform3x4)
8935 batchneed |= BATCHNEED_ARRAY_SKELETAL;
8937 rsurface.batchvertex3f = rsurface.modelvertex3f;
8938 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8939 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8940 rsurface.batchsvector3f = rsurface.modelsvector3f;
8941 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8942 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8943 rsurface.batchtvector3f = rsurface.modeltvector3f;
8944 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8945 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8946 rsurface.batchnormal3f = rsurface.modelnormal3f;
8947 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8948 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8949 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8950 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8951 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8952 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8953 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8954 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8955 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8956 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8957 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8958 rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
8959 rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
8960 rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
8961 rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
8962 rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
8963 rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
8964 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8965 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8966 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8967 rsurface.batchelement3i = rsurface.modelelement3i;
8968 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8969 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8970 rsurface.batchelement3s = rsurface.modelelement3s;
8971 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8972 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8973 rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
8974 rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
8976 // if any dynamic vertex processing has to occur in software, we copy the
8977 // entire surface list together before processing to rebase the vertices
8978 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8980 // if any gaps exist and we do not have a static vertex buffer, we have to
8981 // copy the surface list together to avoid wasting upload bandwidth on the
8982 // vertices in the gaps.
8984 // if gaps exist and we have a static vertex buffer, we can choose whether
8985 // to combine the index buffer ranges into one dynamic index buffer or
8986 // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
8988 // in many cases the batch is reduced to one draw call.
8990 rsurface.batchmultidraw = false;
8991 rsurface.batchmultidrawnumsurfaces = 0;
8992 rsurface.batchmultidrawsurfacelist = NULL;
8996 // static vertex data, just set pointers...
8997 rsurface.batchgeneratedvertex = false;
8998 // if there are gaps, we want to build a combined index buffer,
8999 // otherwise use the original static buffer with an appropriate offset
9002 if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9004 rsurface.batchmultidraw = true;
9005 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9006 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9009 // build a new triangle elements array for this batch
9010 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9011 rsurface.batchfirsttriangle = 0;
9013 for (i = 0;i < texturenumsurfaces;i++)
9015 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9016 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9017 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9018 numtriangles += surfacenumtriangles;
9020 rsurface.batchelement3i_indexbuffer = NULL;
9021 rsurface.batchelement3i_bufferoffset = 0;
9022 rsurface.batchelement3s = NULL;
9023 rsurface.batchelement3s_indexbuffer = NULL;
9024 rsurface.batchelement3s_bufferoffset = 0;
9025 if (endvertex <= 65536)
9027 // make a 16bit (unsigned short) index array if possible
9028 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9029 for (i = 0;i < numtriangles*3;i++)
9030 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9036 // something needs software processing, do it for real...
9037 // we only directly handle separate array data in this case and then
9038 // generate interleaved data if needed...
9039 rsurface.batchgeneratedvertex = true;
9041 // now copy the vertex data into a combined array and make an index array
9042 // (this is what Quake3 does all the time)
9043 // we also apply any skeletal animation here that would have been done in
9044 // the vertex shader, because most of the dynamic vertex animation cases
9045 // need actual vertex positions and normals
9046 //if (dynamicvertex)
9048 rsurface.batchvertex3fbuffer = NULL;
9049 rsurface.batchvertexmesh = NULL;
9050 rsurface.batchvertexmeshbuffer = NULL;
9051 rsurface.batchvertex3f = NULL;
9052 rsurface.batchvertex3f_vertexbuffer = NULL;
9053 rsurface.batchvertex3f_bufferoffset = 0;
9054 rsurface.batchsvector3f = NULL;
9055 rsurface.batchsvector3f_vertexbuffer = NULL;
9056 rsurface.batchsvector3f_bufferoffset = 0;
9057 rsurface.batchtvector3f = NULL;
9058 rsurface.batchtvector3f_vertexbuffer = NULL;
9059 rsurface.batchtvector3f_bufferoffset = 0;
9060 rsurface.batchnormal3f = NULL;
9061 rsurface.batchnormal3f_vertexbuffer = NULL;
9062 rsurface.batchnormal3f_bufferoffset = 0;
9063 rsurface.batchlightmapcolor4f = NULL;
9064 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9065 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9066 rsurface.batchtexcoordtexture2f = NULL;
9067 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9068 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9069 rsurface.batchtexcoordlightmap2f = NULL;
9070 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9071 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9072 rsurface.batchskeletalindex4ub = NULL;
9073 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9074 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9075 rsurface.batchskeletalweight4ub = NULL;
9076 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9077 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9078 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9079 rsurface.batchelement3i_indexbuffer = NULL;
9080 rsurface.batchelement3i_bufferoffset = 0;
9081 rsurface.batchelement3s = NULL;
9082 rsurface.batchelement3s_indexbuffer = NULL;
9083 rsurface.batchelement3s_bufferoffset = 0;
9084 // we'll only be setting up certain arrays as needed
9085 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9086 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9087 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9088 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9089 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9090 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9091 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9093 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9094 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9096 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9097 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9098 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9099 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9100 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9101 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9102 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9104 rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9105 rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9109 for (i = 0;i < texturenumsurfaces;i++)
9111 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9112 surfacenumvertices = texturesurfacelist[i]->num_vertices;
9113 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9114 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9115 // copy only the data requested
9116 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9117 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9118 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9120 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9122 if (rsurface.batchvertex3f)
9123 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9125 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9127 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9129 if (rsurface.modelnormal3f)
9130 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9132 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9134 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9136 if (rsurface.modelsvector3f)
9138 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9139 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9143 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9144 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9147 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9149 if (rsurface.modellightmapcolor4f)
9150 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9152 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9154 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9156 if (rsurface.modeltexcoordtexture2f)
9157 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9159 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9161 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9163 if (rsurface.modeltexcoordlightmap2f)
9164 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9166 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9168 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9170 if (rsurface.modelskeletalindex4ub)
9172 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9173 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9177 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9178 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9179 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9180 for (j = 0;j < surfacenumvertices;j++)
9185 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9186 numvertices += surfacenumvertices;
9187 numtriangles += surfacenumtriangles;
9190 // generate a 16bit index array as well if possible
9191 // (in general, dynamic batches fit)
9192 if (numvertices <= 65536)
9194 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9195 for (i = 0;i < numtriangles*3;i++)
9196 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9199 // since we've copied everything, the batch now starts at 0
9200 rsurface.batchfirstvertex = 0;
9201 rsurface.batchnumvertices = batchnumvertices;
9202 rsurface.batchfirsttriangle = 0;
9203 rsurface.batchnumtriangles = batchnumtriangles;
9206 // apply skeletal animation that would have been done in the vertex shader
9207 if (rsurface.batchskeletaltransform3x4)
9209 const unsigned char *si;
9210 const unsigned char *sw;
9212 const float *b = rsurface.batchskeletaltransform3x4;
9213 float *vp, *vs, *vt, *vn;
9215 float m[3][4], n[3][4];
9216 float tp[3], ts[3], tt[3], tn[3];
9217 si = rsurface.batchskeletalindex4ub;
9218 sw = rsurface.batchskeletalweight4ub;
9219 vp = rsurface.batchvertex3f;
9220 vs = rsurface.batchsvector3f;
9221 vt = rsurface.batchtvector3f;
9222 vn = rsurface.batchnormal3f;
9223 memset(m[0], 0, sizeof(m));
9224 memset(n[0], 0, sizeof(n));
9225 for (i = 0;i < batchnumvertices;i++)
9227 t[0] = b + si[0]*12;
9230 // common case - only one matrix
9244 else if (sw[2] + sw[3])
9247 t[1] = b + si[1]*12;
9248 t[2] = b + si[2]*12;
9249 t[3] = b + si[3]*12;
9250 w[0] = sw[0] * (1.0f / 255.0f);
9251 w[1] = sw[1] * (1.0f / 255.0f);
9252 w[2] = sw[2] * (1.0f / 255.0f);
9253 w[3] = sw[3] * (1.0f / 255.0f);
9254 // blend the matrices
9255 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9256 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9257 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9258 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9259 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9260 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9261 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9262 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9263 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9264 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9265 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9266 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9271 t[1] = b + si[1]*12;
9272 w[0] = sw[0] * (1.0f / 255.0f);
9273 w[1] = sw[1] * (1.0f / 255.0f);
9274 // blend the matrices
9275 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9276 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9277 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9278 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9279 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9280 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9281 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9282 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9283 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9284 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9285 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9286 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9290 // modify the vertex
9292 vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9293 vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9294 vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9298 // the normal transformation matrix is a set of cross products...
9299 CrossProduct(m[1], m[2], n[0]);
9300 CrossProduct(m[2], m[0], n[1]);
9301 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9303 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9304 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9305 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9306 VectorNormalize(vn);
9311 vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9312 vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9313 vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9314 VectorNormalize(vs);
9317 vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9318 vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9319 vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9320 VectorNormalize(vt);
9325 rsurface.batchskeletaltransform3x4 = NULL;
9326 rsurface.batchskeletalnumtransforms = 0;
9329 // q1bsp surfaces rendered in vertex color mode have to have colors
9330 // calculated based on lightstyles
9331 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9333 // generate color arrays for the surfaces in this list
9338 const unsigned char *lm;
9339 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9340 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9341 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9343 for (i = 0;i < texturenumsurfaces;i++)
9345 surface = texturesurfacelist[i];
9346 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9347 surfacenumvertices = surface->num_vertices;
9348 if (surface->lightmapinfo->samples)
9350 for (j = 0;j < surfacenumvertices;j++)
9352 lm = surface->lightmapinfo->samples + offsets[j];
9353 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9354 VectorScale(lm, scale, c);
9355 if (surface->lightmapinfo->styles[1] != 255)
9357 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9359 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9360 VectorMA(c, scale, lm, c);
9361 if (surface->lightmapinfo->styles[2] != 255)
9364 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9365 VectorMA(c, scale, lm, c);
9366 if (surface->lightmapinfo->styles[3] != 255)
9369 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9370 VectorMA(c, scale, lm, c);
9377 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);
9383 for (j = 0;j < surfacenumvertices;j++)
9385 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9392 // if vertices are deformed (sprite flares and things in maps, possibly
9393 // water waves, bulges and other deformations), modify the copied vertices
9395 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9397 switch (deform->deform)
9400 case Q3DEFORM_PROJECTIONSHADOW:
9401 case Q3DEFORM_TEXT0:
9402 case Q3DEFORM_TEXT1:
9403 case Q3DEFORM_TEXT2:
9404 case Q3DEFORM_TEXT3:
9405 case Q3DEFORM_TEXT4:
9406 case Q3DEFORM_TEXT5:
9407 case Q3DEFORM_TEXT6:
9408 case Q3DEFORM_TEXT7:
9411 case Q3DEFORM_AUTOSPRITE:
9412 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9413 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9414 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9415 VectorNormalize(newforward);
9416 VectorNormalize(newright);
9417 VectorNormalize(newup);
9418 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9419 // rsurface.batchvertex3f_vertexbuffer = NULL;
9420 // rsurface.batchvertex3f_bufferoffset = 0;
9421 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9422 // rsurface.batchsvector3f_vertexbuffer = NULL;
9423 // rsurface.batchsvector3f_bufferoffset = 0;
9424 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9425 // rsurface.batchtvector3f_vertexbuffer = NULL;
9426 // rsurface.batchtvector3f_bufferoffset = 0;
9427 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9428 // rsurface.batchnormal3f_vertexbuffer = NULL;
9429 // rsurface.batchnormal3f_bufferoffset = 0;
9430 // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9431 if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9432 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9433 if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9434 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);
9435 // a single autosprite surface can contain multiple sprites...
9436 for (j = 0;j < batchnumvertices - 3;j += 4)
9438 VectorClear(center);
9439 for (i = 0;i < 4;i++)
9440 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9441 VectorScale(center, 0.25f, center);
9442 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9443 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9444 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9445 for (i = 0;i < 4;i++)
9447 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9448 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9451 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9452 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9453 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);
9455 case Q3DEFORM_AUTOSPRITE2:
9456 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9457 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9458 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9459 VectorNormalize(newforward);
9460 VectorNormalize(newright);
9461 VectorNormalize(newup);
9462 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9463 // rsurface.batchvertex3f_vertexbuffer = NULL;
9464 // rsurface.batchvertex3f_bufferoffset = 0;
9466 const float *v1, *v2;
9476 memset(shortest, 0, sizeof(shortest));
9477 // a single autosprite surface can contain multiple sprites...
9478 for (j = 0;j < batchnumvertices - 3;j += 4)
9480 VectorClear(center);
9481 for (i = 0;i < 4;i++)
9482 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9483 VectorScale(center, 0.25f, center);
9484 // find the two shortest edges, then use them to define the
9485 // axis vectors for rotating around the central axis
9486 for (i = 0;i < 6;i++)
9488 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9489 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9490 l = VectorDistance2(v1, v2);
9491 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9493 l += (1.0f / 1024.0f);
9494 if (shortest[0].length2 > l || i == 0)
9496 shortest[1] = shortest[0];
9497 shortest[0].length2 = l;
9498 shortest[0].v1 = v1;
9499 shortest[0].v2 = v2;
9501 else if (shortest[1].length2 > l || i == 1)
9503 shortest[1].length2 = l;
9504 shortest[1].v1 = v1;
9505 shortest[1].v2 = v2;
9508 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9509 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9510 // this calculates the right vector from the shortest edge
9511 // and the up vector from the edge midpoints
9512 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9513 VectorNormalize(right);
9514 VectorSubtract(end, start, up);
9515 VectorNormalize(up);
9516 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9517 VectorSubtract(rsurface.localvieworigin, center, forward);
9518 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9519 VectorNegate(forward, forward);
9520 VectorReflect(forward, 0, up, forward);
9521 VectorNormalize(forward);
9522 CrossProduct(up, forward, newright);
9523 VectorNormalize(newright);
9524 // rotate the quad around the up axis vector, this is made
9525 // especially easy by the fact we know the quad is flat,
9526 // so we only have to subtract the center position and
9527 // measure distance along the right vector, and then
9528 // multiply that by the newright vector and add back the
9530 // we also need to subtract the old position to undo the
9531 // displacement from the center, which we do with a
9532 // DotProduct, the subtraction/addition of center is also
9533 // optimized into DotProducts here
9534 l = DotProduct(right, center);
9535 for (i = 0;i < 4;i++)
9537 v1 = rsurface.batchvertex3f + 3*(j+i);
9538 f = DotProduct(right, v1) - l;
9539 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9543 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9545 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9546 // rsurface.batchnormal3f_vertexbuffer = NULL;
9547 // rsurface.batchnormal3f_bufferoffset = 0;
9548 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9550 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9552 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9553 // rsurface.batchsvector3f_vertexbuffer = NULL;
9554 // rsurface.batchsvector3f_bufferoffset = 0;
9555 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9556 // rsurface.batchtvector3f_vertexbuffer = NULL;
9557 // rsurface.batchtvector3f_bufferoffset = 0;
9558 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);
9561 case Q3DEFORM_NORMAL:
9562 // deform the normals to make reflections wavey
9563 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9564 rsurface.batchnormal3f_vertexbuffer = NULL;
9565 rsurface.batchnormal3f_bufferoffset = 0;
9566 for (j = 0;j < batchnumvertices;j++)
9569 float *normal = rsurface.batchnormal3f + 3*j;
9570 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9571 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9572 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9573 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9574 VectorNormalize(normal);
9576 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9578 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9579 // rsurface.batchsvector3f_vertexbuffer = NULL;
9580 // rsurface.batchsvector3f_bufferoffset = 0;
9581 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9582 // rsurface.batchtvector3f_vertexbuffer = NULL;
9583 // rsurface.batchtvector3f_bufferoffset = 0;
9584 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);
9588 // deform vertex array to make wavey water and flags and such
9589 waveparms[0] = deform->waveparms[0];
9590 waveparms[1] = deform->waveparms[1];
9591 waveparms[2] = deform->waveparms[2];
9592 waveparms[3] = deform->waveparms[3];
9593 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9594 break; // if wavefunc is a nop, don't make a dynamic vertex array
9595 // this is how a divisor of vertex influence on deformation
9596 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9597 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9598 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9599 // rsurface.batchvertex3f_vertexbuffer = NULL;
9600 // rsurface.batchvertex3f_bufferoffset = 0;
9601 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9602 // rsurface.batchnormal3f_vertexbuffer = NULL;
9603 // rsurface.batchnormal3f_bufferoffset = 0;
9604 for (j = 0;j < batchnumvertices;j++)
9606 // if the wavefunc depends on time, evaluate it per-vertex
9609 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9610 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9612 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9614 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9615 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9616 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9618 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9619 // rsurface.batchsvector3f_vertexbuffer = NULL;
9620 // rsurface.batchsvector3f_bufferoffset = 0;
9621 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9622 // rsurface.batchtvector3f_vertexbuffer = NULL;
9623 // rsurface.batchtvector3f_bufferoffset = 0;
9624 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);
9627 case Q3DEFORM_BULGE:
9628 // deform vertex array to make the surface have moving bulges
9629 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9630 // rsurface.batchvertex3f_vertexbuffer = NULL;
9631 // rsurface.batchvertex3f_bufferoffset = 0;
9632 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9633 // rsurface.batchnormal3f_vertexbuffer = NULL;
9634 // rsurface.batchnormal3f_bufferoffset = 0;
9635 for (j = 0;j < batchnumvertices;j++)
9637 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9638 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9640 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9641 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9642 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9644 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9645 // rsurface.batchsvector3f_vertexbuffer = NULL;
9646 // rsurface.batchsvector3f_bufferoffset = 0;
9647 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9648 // rsurface.batchtvector3f_vertexbuffer = NULL;
9649 // rsurface.batchtvector3f_bufferoffset = 0;
9650 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);
9654 // deform vertex array
9655 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9656 break; // if wavefunc is a nop, don't make a dynamic vertex array
9657 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9658 VectorScale(deform->parms, scale, waveparms);
9659 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9660 // rsurface.batchvertex3f_vertexbuffer = NULL;
9661 // rsurface.batchvertex3f_bufferoffset = 0;
9662 for (j = 0;j < batchnumvertices;j++)
9663 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9668 // generate texcoords based on the chosen texcoord source
9669 switch(rsurface.texture->tcgen.tcgen)
9672 case Q3TCGEN_TEXTURE:
9674 case Q3TCGEN_LIGHTMAP:
9675 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9676 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9677 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9678 if (rsurface.batchtexcoordlightmap2f)
9679 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9681 case Q3TCGEN_VECTOR:
9682 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9683 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9684 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9685 for (j = 0;j < batchnumvertices;j++)
9687 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9688 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9691 case Q3TCGEN_ENVIRONMENT:
9692 // make environment reflections using a spheremap
9693 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9694 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9695 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9696 for (j = 0;j < batchnumvertices;j++)
9698 // identical to Q3A's method, but executed in worldspace so
9699 // carried models can be shiny too
9701 float viewer[3], d, reflected[3], worldreflected[3];
9703 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9704 // VectorNormalize(viewer);
9706 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9708 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9709 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9710 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9711 // note: this is proportinal to viewer, so we can normalize later
9713 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9714 VectorNormalize(worldreflected);
9716 // note: this sphere map only uses world x and z!
9717 // so positive and negative y will LOOK THE SAME.
9718 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9719 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9723 // the only tcmod that needs software vertex processing is turbulent, so
9724 // check for it here and apply the changes if needed
9725 // and we only support that as the first one
9726 // (handling a mixture of turbulent and other tcmods would be problematic
9727 // without punting it entirely to a software path)
9728 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9730 amplitude = rsurface.texture->tcmods[0].parms[1];
9731 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9732 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9733 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9734 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9735 for (j = 0;j < batchnumvertices;j++)
9737 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);
9738 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9742 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9744 // convert the modified arrays to vertex structs
9745 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9746 // rsurface.batchvertexmeshbuffer = NULL;
9747 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9748 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9749 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9750 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9751 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9752 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9753 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9755 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9757 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9758 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9761 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9762 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9763 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9764 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9765 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9766 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9767 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9768 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9769 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9770 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
9772 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9774 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
9775 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
9781 void RSurf_DrawBatch(void)
9783 // sometimes a zero triangle surface (usually a degenerate patch) makes it
9784 // through the pipeline, killing it earlier in the pipeline would have
9785 // per-surface overhead rather than per-batch overhead, so it's best to
9786 // reject it here, before it hits glDraw.
9787 if (rsurface.batchnumtriangles == 0)
9790 // batch debugging code
9791 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9797 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9798 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9801 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9803 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9805 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9806 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);
9813 if (rsurface.batchmultidraw)
9815 // issue multiple draws rather than copying index data
9816 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
9817 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
9818 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
9819 for (i = 0;i < numsurfaces;)
9821 // combine consecutive surfaces as one draw
9822 for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
9823 if (surfacelist[j] != surfacelist[k] + 1)
9825 firstvertex = surfacelist[i]->num_firstvertex;
9826 endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
9827 firsttriangle = surfacelist[i]->num_firsttriangle;
9828 endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
9829 R_Mesh_Draw(firstvertex, endvertex - firstvertex, firsttriangle, endtriangle - firsttriangle, rsurface.batchelement3i, rsurface.batchelement3i_indexbuffer, rsurface.batchelement3i_bufferoffset, rsurface.batchelement3s, rsurface.batchelement3s_indexbuffer, rsurface.batchelement3s_bufferoffset);
9835 // there is only one consecutive run of index data (may have been combined)
9836 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);
9840 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9842 // pick the closest matching water plane
9843 int planeindex, vertexindex, bestplaneindex = -1;
9847 r_waterstate_waterplane_t *p;
9848 qboolean prepared = false;
9850 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
9852 if(p->camera_entity != rsurface.texture->camera_entity)
9857 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
9859 if(rsurface.batchnumvertices == 0)
9862 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9864 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9865 d += fabs(PlaneDiff(vert, &p->plane));
9867 if (bestd > d || bestplaneindex < 0)
9870 bestplaneindex = planeindex;
9873 return bestplaneindex;
9874 // NOTE: this MAY return a totally unrelated water plane; we can ignore
9875 // this situation though, as it might be better to render single larger
9876 // batches with useless stuff (backface culled for example) than to
9877 // render multiple smaller batches
9880 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9883 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9884 rsurface.passcolor4f_vertexbuffer = 0;
9885 rsurface.passcolor4f_bufferoffset = 0;
9886 for (i = 0;i < rsurface.batchnumvertices;i++)
9887 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9890 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9897 if (rsurface.passcolor4f)
9899 // generate color arrays
9900 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9901 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9902 rsurface.passcolor4f_vertexbuffer = 0;
9903 rsurface.passcolor4f_bufferoffset = 0;
9904 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)
9906 f = RSurf_FogVertex(v);
9915 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9916 rsurface.passcolor4f_vertexbuffer = 0;
9917 rsurface.passcolor4f_bufferoffset = 0;
9918 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9920 f = RSurf_FogVertex(v);
9929 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9936 if (!rsurface.passcolor4f)
9938 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9939 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9940 rsurface.passcolor4f_vertexbuffer = 0;
9941 rsurface.passcolor4f_bufferoffset = 0;
9942 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)
9944 f = RSurf_FogVertex(v);
9945 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9946 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9947 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9952 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9957 if (!rsurface.passcolor4f)
9959 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9960 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9961 rsurface.passcolor4f_vertexbuffer = 0;
9962 rsurface.passcolor4f_bufferoffset = 0;
9963 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9972 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9977 if (!rsurface.passcolor4f)
9979 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9980 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9981 rsurface.passcolor4f_vertexbuffer = 0;
9982 rsurface.passcolor4f_bufferoffset = 0;
9983 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9985 c2[0] = c[0] + r_refdef.scene.ambient;
9986 c2[1] = c[1] + r_refdef.scene.ambient;
9987 c2[2] = c[2] + r_refdef.scene.ambient;
9992 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9995 rsurface.passcolor4f = NULL;
9996 rsurface.passcolor4f_vertexbuffer = 0;
9997 rsurface.passcolor4f_bufferoffset = 0;
9998 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9999 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10000 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10001 GL_Color(r, g, b, a);
10002 R_Mesh_TexBind(0, rsurface.lightmaptexture);
10006 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10008 // TODO: optimize applyfog && applycolor case
10009 // just apply fog if necessary, and tint the fog color array if necessary
10010 rsurface.passcolor4f = NULL;
10011 rsurface.passcolor4f_vertexbuffer = 0;
10012 rsurface.passcolor4f_bufferoffset = 0;
10013 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10014 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10015 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10016 GL_Color(r, g, b, a);
10020 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10023 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10024 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10025 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10026 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10027 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10028 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10029 GL_Color(r, g, b, a);
10033 static void RSurf_DrawBatch_GL11_ClampColor(void)
10038 if (!rsurface.passcolor4f)
10040 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10042 c2[0] = bound(0.0f, c1[0], 1.0f);
10043 c2[1] = bound(0.0f, c1[1], 1.0f);
10044 c2[2] = bound(0.0f, c1[2], 1.0f);
10045 c2[3] = bound(0.0f, c1[3], 1.0f);
10049 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10059 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10060 rsurface.passcolor4f_vertexbuffer = 0;
10061 rsurface.passcolor4f_bufferoffset = 0;
10062 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)
10064 f = -DotProduct(r_refdef.view.forward, n);
10066 f = f * 0.85 + 0.15; // work around so stuff won't get black
10067 f *= r_refdef.lightmapintensity;
10068 Vector4Set(c, f, f, f, 1);
10072 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10074 RSurf_DrawBatch_GL11_ApplyFakeLight();
10075 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10076 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10077 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10078 GL_Color(r, g, b, a);
10082 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10090 vec3_t ambientcolor;
10091 vec3_t diffusecolor;
10095 VectorCopy(rsurface.modellight_lightdir, lightdir);
10096 f = 0.5f * r_refdef.lightmapintensity;
10097 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10098 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10099 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10100 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10101 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10102 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10104 if (VectorLength2(diffusecolor) > 0)
10106 // q3-style directional shading
10107 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10108 rsurface.passcolor4f_vertexbuffer = 0;
10109 rsurface.passcolor4f_bufferoffset = 0;
10110 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)
10112 if ((f = DotProduct(n, lightdir)) > 0)
10113 VectorMA(ambientcolor, f, diffusecolor, c);
10115 VectorCopy(ambientcolor, c);
10122 *applycolor = false;
10126 *r = ambientcolor[0];
10127 *g = ambientcolor[1];
10128 *b = ambientcolor[2];
10129 rsurface.passcolor4f = NULL;
10130 rsurface.passcolor4f_vertexbuffer = 0;
10131 rsurface.passcolor4f_bufferoffset = 0;
10135 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10137 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10138 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10139 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10140 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10141 GL_Color(r, g, b, a);
10145 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10153 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10154 rsurface.passcolor4f_vertexbuffer = 0;
10155 rsurface.passcolor4f_bufferoffset = 0;
10157 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10159 f = 1 - RSurf_FogVertex(v);
10167 void RSurf_SetupDepthAndCulling(void)
10169 // submodels are biased to avoid z-fighting with world surfaces that they
10170 // may be exactly overlapping (avoids z-fighting artifacts on certain
10171 // doors and things in Quake maps)
10172 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10173 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10174 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10175 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10178 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10180 // transparent sky would be ridiculous
10181 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10183 R_SetupShader_Generic_NoTexture(false, false);
10184 skyrenderlater = true;
10185 RSurf_SetupDepthAndCulling();
10186 GL_DepthMask(true);
10187 // LordHavoc: HalfLife maps have freaky skypolys so don't use
10188 // skymasking on them, and Quake3 never did sky masking (unlike
10189 // software Quake and software Quake2), so disable the sky masking
10190 // in Quake3 maps as it causes problems with q3map2 sky tricks,
10191 // and skymasking also looks very bad when noclipping outside the
10192 // level, so don't use it then either.
10193 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10195 R_Mesh_ResetTextureState();
10196 if (skyrendermasked)
10198 R_SetupShader_DepthOrShadow(false, false, false);
10199 // depth-only (masking)
10200 GL_ColorMask(0,0,0,0);
10201 // just to make sure that braindead drivers don't draw
10202 // anything despite that colormask...
10203 GL_BlendFunc(GL_ZERO, GL_ONE);
10204 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10205 if (rsurface.batchvertex3fbuffer)
10206 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10208 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10212 R_SetupShader_Generic_NoTexture(false, false);
10214 GL_BlendFunc(GL_ONE, GL_ZERO);
10215 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10216 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10217 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10220 if (skyrendermasked)
10221 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10223 R_Mesh_ResetTextureState();
10224 GL_Color(1, 1, 1, 1);
10227 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10228 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10229 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10231 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10235 // render screenspace normalmap to texture
10236 GL_DepthMask(true);
10237 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10242 // bind lightmap texture
10244 // water/refraction/reflection/camera surfaces have to be handled specially
10245 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10247 int start, end, startplaneindex;
10248 for (start = 0;start < texturenumsurfaces;start = end)
10250 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10251 if(startplaneindex < 0)
10253 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10254 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10258 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10260 // now that we have a batch using the same planeindex, render it
10261 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10263 // render water or distortion background
10264 GL_DepthMask(true);
10265 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);
10267 // blend surface on top
10268 GL_DepthMask(false);
10269 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10272 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10274 // render surface with reflection texture as input
10275 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10276 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);
10283 // render surface batch normally
10284 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10285 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);
10289 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10291 // OpenGL 1.3 path - anything not completely ancient
10292 qboolean applycolor;
10295 const texturelayer_t *layer;
10296 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);
10297 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10299 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10302 int layertexrgbscale;
10303 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10305 if (layerindex == 0)
10306 GL_AlphaTest(true);
10309 GL_AlphaTest(false);
10310 GL_DepthFunc(GL_EQUAL);
10313 GL_DepthMask(layer->depthmask && writedepth);
10314 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10315 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10317 layertexrgbscale = 4;
10318 VectorScale(layer->color, 0.25f, layercolor);
10320 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10322 layertexrgbscale = 2;
10323 VectorScale(layer->color, 0.5f, layercolor);
10327 layertexrgbscale = 1;
10328 VectorScale(layer->color, 1.0f, layercolor);
10330 layercolor[3] = layer->color[3];
10331 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10332 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10333 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10334 switch (layer->type)
10336 case TEXTURELAYERTYPE_LITTEXTURE:
10337 // single-pass lightmapped texture with 2x rgbscale
10338 R_Mesh_TexBind(0, r_texture_white);
10339 R_Mesh_TexMatrix(0, NULL);
10340 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10341 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10342 R_Mesh_TexBind(1, layer->texture);
10343 R_Mesh_TexMatrix(1, &layer->texmatrix);
10344 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10345 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10346 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10347 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10348 else if (FAKELIGHT_ENABLED)
10349 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10350 else if (rsurface.uselightmaptexture)
10351 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10353 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10355 case TEXTURELAYERTYPE_TEXTURE:
10356 // singletexture unlit texture with transparency support
10357 R_Mesh_TexBind(0, layer->texture);
10358 R_Mesh_TexMatrix(0, &layer->texmatrix);
10359 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10360 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10361 R_Mesh_TexBind(1, 0);
10362 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10363 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10365 case TEXTURELAYERTYPE_FOG:
10366 // singletexture fogging
10367 if (layer->texture)
10369 R_Mesh_TexBind(0, layer->texture);
10370 R_Mesh_TexMatrix(0, &layer->texmatrix);
10371 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10372 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10376 R_Mesh_TexBind(0, 0);
10377 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10379 R_Mesh_TexBind(1, 0);
10380 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10381 // generate a color array for the fog pass
10382 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10383 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10387 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10390 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10392 GL_DepthFunc(GL_LEQUAL);
10393 GL_AlphaTest(false);
10397 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10399 // OpenGL 1.1 - crusty old voodoo path
10402 const texturelayer_t *layer;
10403 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);
10404 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10406 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10408 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10410 if (layerindex == 0)
10411 GL_AlphaTest(true);
10414 GL_AlphaTest(false);
10415 GL_DepthFunc(GL_EQUAL);
10418 GL_DepthMask(layer->depthmask && writedepth);
10419 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10420 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10421 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10422 switch (layer->type)
10424 case TEXTURELAYERTYPE_LITTEXTURE:
10425 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10427 // two-pass lit texture with 2x rgbscale
10428 // first the lightmap pass
10429 R_Mesh_TexBind(0, r_texture_white);
10430 R_Mesh_TexMatrix(0, NULL);
10431 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10432 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10433 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10434 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10435 else if (FAKELIGHT_ENABLED)
10436 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10437 else if (rsurface.uselightmaptexture)
10438 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10440 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10441 // then apply the texture to it
10442 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10443 R_Mesh_TexBind(0, layer->texture);
10444 R_Mesh_TexMatrix(0, &layer->texmatrix);
10445 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10446 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10447 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);
10451 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10452 R_Mesh_TexBind(0, layer->texture);
10453 R_Mesh_TexMatrix(0, &layer->texmatrix);
10454 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10455 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10456 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10457 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);
10458 else if (FAKELIGHT_ENABLED)
10459 RSurf_DrawBatch_GL11_FakeLight(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);
10461 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);
10464 case TEXTURELAYERTYPE_TEXTURE:
10465 // singletexture unlit texture with transparency support
10466 R_Mesh_TexBind(0, layer->texture);
10467 R_Mesh_TexMatrix(0, &layer->texmatrix);
10468 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10469 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10470 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);
10472 case TEXTURELAYERTYPE_FOG:
10473 // singletexture fogging
10474 if (layer->texture)
10476 R_Mesh_TexBind(0, layer->texture);
10477 R_Mesh_TexMatrix(0, &layer->texmatrix);
10478 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10479 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10483 R_Mesh_TexBind(0, 0);
10484 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10486 // generate a color array for the fog pass
10487 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10488 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10492 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10495 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10497 GL_DepthFunc(GL_LEQUAL);
10498 GL_AlphaTest(false);
10502 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10506 r_vertexgeneric_t *batchvertex;
10509 // R_Mesh_ResetTextureState();
10510 R_SetupShader_Generic_NoTexture(false, false);
10512 if(rsurface.texture && rsurface.texture->currentskinframe)
10514 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10515 c[3] *= rsurface.texture->currentalpha;
10525 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10527 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10528 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10529 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10532 // brighten it up (as texture value 127 means "unlit")
10533 c[0] *= 2 * r_refdef.view.colorscale;
10534 c[1] *= 2 * r_refdef.view.colorscale;
10535 c[2] *= 2 * r_refdef.view.colorscale;
10537 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10538 c[3] *= r_wateralpha.value;
10540 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10542 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10543 GL_DepthMask(false);
10545 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10547 GL_BlendFunc(GL_ONE, GL_ONE);
10548 GL_DepthMask(false);
10550 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10552 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10553 GL_DepthMask(false);
10555 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10557 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10558 GL_DepthMask(false);
10562 GL_BlendFunc(GL_ONE, GL_ZERO);
10563 GL_DepthMask(writedepth);
10566 if (r_showsurfaces.integer == 3)
10568 rsurface.passcolor4f = NULL;
10570 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10572 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10574 rsurface.passcolor4f = NULL;
10575 rsurface.passcolor4f_vertexbuffer = 0;
10576 rsurface.passcolor4f_bufferoffset = 0;
10578 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10580 qboolean applycolor = true;
10583 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10585 r_refdef.lightmapintensity = 1;
10586 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10587 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10589 else if (FAKELIGHT_ENABLED)
10591 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10593 r_refdef.lightmapintensity = r_fakelight_intensity.value;
10594 RSurf_DrawBatch_GL11_ApplyFakeLight();
10595 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10599 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10601 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10602 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10603 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10606 if(!rsurface.passcolor4f)
10607 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10609 RSurf_DrawBatch_GL11_ApplyAmbient();
10610 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10611 if(r_refdef.fogenabled)
10612 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10613 RSurf_DrawBatch_GL11_ClampColor();
10615 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10616 R_SetupShader_Generic_NoTexture(false, false);
10619 else if (!r_refdef.view.showdebug)
10621 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10622 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10623 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
10625 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10626 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10628 R_Mesh_PrepareVertices_Generic_Unlock();
10631 else if (r_showsurfaces.integer == 4)
10633 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10634 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10635 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
10637 unsigned char c = (vi << 3) * (1.0f / 256.0f);
10638 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10639 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10641 R_Mesh_PrepareVertices_Generic_Unlock();
10644 else if (r_showsurfaces.integer == 2)
10647 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10648 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10649 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10651 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10652 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10653 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10654 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10655 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10656 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10657 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10659 R_Mesh_PrepareVertices_Generic_Unlock();
10660 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10664 int texturesurfaceindex;
10666 const msurface_t *surface;
10667 float surfacecolor4f[4];
10668 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10669 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10671 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10673 surface = texturesurfacelist[texturesurfaceindex];
10674 k = (int)(((size_t)surface) / sizeof(msurface_t));
10675 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10676 for (j = 0;j < surface->num_vertices;j++)
10678 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10679 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10683 R_Mesh_PrepareVertices_Generic_Unlock();
10688 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10691 RSurf_SetupDepthAndCulling();
10692 if (r_showsurfaces.integer)
10694 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10697 switch (vid.renderpath)
10699 case RENDERPATH_GL20:
10700 case RENDERPATH_D3D9:
10701 case RENDERPATH_D3D10:
10702 case RENDERPATH_D3D11:
10703 case RENDERPATH_SOFT:
10704 case RENDERPATH_GLES2:
10705 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10707 case RENDERPATH_GL13:
10708 case RENDERPATH_GLES1:
10709 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10711 case RENDERPATH_GL11:
10712 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10718 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10721 RSurf_SetupDepthAndCulling();
10722 if (r_showsurfaces.integer)
10724 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10727 switch (vid.renderpath)
10729 case RENDERPATH_GL20:
10730 case RENDERPATH_D3D9:
10731 case RENDERPATH_D3D10:
10732 case RENDERPATH_D3D11:
10733 case RENDERPATH_SOFT:
10734 case RENDERPATH_GLES2:
10735 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10737 case RENDERPATH_GL13:
10738 case RENDERPATH_GLES1:
10739 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10741 case RENDERPATH_GL11:
10742 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10748 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10751 int texturenumsurfaces, endsurface;
10752 texture_t *texture;
10753 const msurface_t *surface;
10754 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10756 // if the model is static it doesn't matter what value we give for
10757 // wantnormals and wanttangents, so this logic uses only rules applicable
10758 // to a model, knowing that they are meaningless otherwise
10759 if (ent == r_refdef.scene.worldentity)
10760 RSurf_ActiveWorldEntity();
10761 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10762 RSurf_ActiveModelEntity(ent, false, false, false);
10765 switch (vid.renderpath)
10767 case RENDERPATH_GL20:
10768 case RENDERPATH_D3D9:
10769 case RENDERPATH_D3D10:
10770 case RENDERPATH_D3D11:
10771 case RENDERPATH_SOFT:
10772 case RENDERPATH_GLES2:
10773 RSurf_ActiveModelEntity(ent, true, true, false);
10775 case RENDERPATH_GL11:
10776 case RENDERPATH_GL13:
10777 case RENDERPATH_GLES1:
10778 RSurf_ActiveModelEntity(ent, true, false, false);
10783 if (r_transparentdepthmasking.integer)
10785 qboolean setup = false;
10786 for (i = 0;i < numsurfaces;i = j)
10789 surface = rsurface.modelsurfaces + surfacelist[i];
10790 texture = surface->texture;
10791 rsurface.texture = R_GetCurrentTexture(texture);
10792 rsurface.lightmaptexture = NULL;
10793 rsurface.deluxemaptexture = NULL;
10794 rsurface.uselightmaptexture = false;
10795 // scan ahead until we find a different texture
10796 endsurface = min(i + 1024, numsurfaces);
10797 texturenumsurfaces = 0;
10798 texturesurfacelist[texturenumsurfaces++] = surface;
10799 for (;j < endsurface;j++)
10801 surface = rsurface.modelsurfaces + surfacelist[j];
10802 if (texture != surface->texture)
10804 texturesurfacelist[texturenumsurfaces++] = surface;
10806 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10808 // render the range of surfaces as depth
10812 GL_ColorMask(0,0,0,0);
10814 GL_DepthTest(true);
10815 GL_BlendFunc(GL_ONE, GL_ZERO);
10816 GL_DepthMask(true);
10817 // R_Mesh_ResetTextureState();
10819 RSurf_SetupDepthAndCulling();
10820 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10821 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
10822 if (rsurface.batchvertex3fbuffer)
10823 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10825 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10829 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10832 for (i = 0;i < numsurfaces;i = j)
10835 surface = rsurface.modelsurfaces + surfacelist[i];
10836 texture = surface->texture;
10837 rsurface.texture = R_GetCurrentTexture(texture);
10838 // scan ahead until we find a different texture
10839 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10840 texturenumsurfaces = 0;
10841 texturesurfacelist[texturenumsurfaces++] = surface;
10842 if(FAKELIGHT_ENABLED)
10844 rsurface.lightmaptexture = NULL;
10845 rsurface.deluxemaptexture = NULL;
10846 rsurface.uselightmaptexture = false;
10847 for (;j < endsurface;j++)
10849 surface = rsurface.modelsurfaces + surfacelist[j];
10850 if (texture != surface->texture)
10852 texturesurfacelist[texturenumsurfaces++] = surface;
10857 rsurface.lightmaptexture = surface->lightmaptexture;
10858 rsurface.deluxemaptexture = surface->deluxemaptexture;
10859 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10860 for (;j < endsurface;j++)
10862 surface = rsurface.modelsurfaces + surfacelist[j];
10863 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10865 texturesurfacelist[texturenumsurfaces++] = surface;
10868 // render the range of surfaces
10869 if (ent == r_refdef.scene.worldentity)
10870 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10872 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10874 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10877 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10879 // transparent surfaces get pushed off into the transparent queue
10880 int surfacelistindex;
10881 const msurface_t *surface;
10882 vec3_t tempcenter, center;
10883 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10885 surface = texturesurfacelist[surfacelistindex];
10886 if (r_transparent_sortsurfacesbynearest.integer)
10888 tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
10889 tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
10890 tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
10894 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10895 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10896 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10898 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10899 if (rsurface.entity->transparent_offset) // transparent offset
10901 center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
10902 center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
10903 center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
10905 R_MeshQueue_AddTransparent((rsurface.entity->flags & RENDER_WORLDOBJECT) ? TRANSPARENTSORT_SKY : (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST) ? TRANSPARENTSORT_HUD : rsurface.texture->transparentsort, center, R_DrawSurface_TransparentCallback, rsurface.entity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10909 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10911 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10913 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10915 RSurf_SetupDepthAndCulling();
10916 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10917 if (rsurface.batchvertex3fbuffer)
10918 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10920 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10921 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
10925 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10929 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10932 if (!rsurface.texture->currentnumlayers)
10934 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10935 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10937 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10939 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10940 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10941 else if (!rsurface.texture->currentnumlayers)
10943 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
10945 // in the deferred case, transparent surfaces were queued during prepass
10946 if (!r_shadow_usingdeferredprepass)
10947 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10951 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10952 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10957 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10960 texture_t *texture;
10961 R_FrameData_SetMark();
10962 // break the surface list down into batches by texture and use of lightmapping
10963 for (i = 0;i < numsurfaces;i = j)
10966 // texture is the base texture pointer, rsurface.texture is the
10967 // current frame/skin the texture is directing us to use (for example
10968 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10969 // use skin 1 instead)
10970 texture = surfacelist[i]->texture;
10971 rsurface.texture = R_GetCurrentTexture(texture);
10972 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10974 // if this texture is not the kind we want, skip ahead to the next one
10975 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10979 if(FAKELIGHT_ENABLED || depthonly || prepass)
10981 rsurface.lightmaptexture = NULL;
10982 rsurface.deluxemaptexture = NULL;
10983 rsurface.uselightmaptexture = false;
10984 // simply scan ahead until we find a different texture or lightmap state
10985 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10990 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10991 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10992 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10993 // simply scan ahead until we find a different texture or lightmap state
10994 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10997 // render the range of surfaces
10998 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11000 R_FrameData_ReturnToMark();
11003 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11007 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11010 if (!rsurface.texture->currentnumlayers)
11012 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11013 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11015 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11017 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11018 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11019 else if (!rsurface.texture->currentnumlayers)
11021 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11023 // in the deferred case, transparent surfaces were queued during prepass
11024 if (!r_shadow_usingdeferredprepass)
11025 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11029 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11030 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11035 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11038 texture_t *texture;
11039 R_FrameData_SetMark();
11040 // break the surface list down into batches by texture and use of lightmapping
11041 for (i = 0;i < numsurfaces;i = j)
11044 // texture is the base texture pointer, rsurface.texture is the
11045 // current frame/skin the texture is directing us to use (for example
11046 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11047 // use skin 1 instead)
11048 texture = surfacelist[i]->texture;
11049 rsurface.texture = R_GetCurrentTexture(texture);
11050 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11052 // if this texture is not the kind we want, skip ahead to the next one
11053 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11057 if(FAKELIGHT_ENABLED || depthonly || prepass)
11059 rsurface.lightmaptexture = NULL;
11060 rsurface.deluxemaptexture = NULL;
11061 rsurface.uselightmaptexture = false;
11062 // simply scan ahead until we find a different texture or lightmap state
11063 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11068 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11069 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11070 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11071 // simply scan ahead until we find a different texture or lightmap state
11072 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11075 // render the range of surfaces
11076 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11078 R_FrameData_ReturnToMark();
11081 float locboxvertex3f[6*4*3] =
11083 1,0,1, 1,0,0, 1,1,0, 1,1,1,
11084 0,1,1, 0,1,0, 0,0,0, 0,0,1,
11085 1,1,1, 1,1,0, 0,1,0, 0,1,1,
11086 0,0,1, 0,0,0, 1,0,0, 1,0,1,
11087 0,0,1, 1,0,1, 1,1,1, 0,1,1,
11088 1,0,0, 0,0,0, 0,1,0, 1,1,0
11091 unsigned short locboxelements[6*2*3] =
11096 12,13,14, 12,14,15,
11097 16,17,18, 16,18,19,
11101 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11104 cl_locnode_t *loc = (cl_locnode_t *)ent;
11106 float vertex3f[6*4*3];
11108 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11109 GL_DepthMask(false);
11110 GL_DepthRange(0, 1);
11111 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11112 GL_DepthTest(true);
11113 GL_CullFace(GL_NONE);
11114 R_EntityMatrix(&identitymatrix);
11116 // R_Mesh_ResetTextureState();
11118 i = surfacelist[0];
11119 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11120 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11121 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11122 surfacelist[0] < 0 ? 0.5f : 0.125f);
11124 if (VectorCompare(loc->mins, loc->maxs))
11126 VectorSet(size, 2, 2, 2);
11127 VectorMA(loc->mins, -0.5f, size, mins);
11131 VectorCopy(loc->mins, mins);
11132 VectorSubtract(loc->maxs, loc->mins, size);
11135 for (i = 0;i < 6*4*3;)
11136 for (j = 0;j < 3;j++, i++)
11137 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11139 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11140 R_SetupShader_Generic_NoTexture(false, false);
11141 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11144 void R_DrawLocs(void)
11147 cl_locnode_t *loc, *nearestloc;
11149 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11150 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11152 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11153 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11157 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11159 if (decalsystem->decals)
11160 Mem_Free(decalsystem->decals);
11161 memset(decalsystem, 0, sizeof(*decalsystem));
11164 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)
11167 tridecal_t *decals;
11170 // expand or initialize the system
11171 if (decalsystem->maxdecals <= decalsystem->numdecals)
11173 decalsystem_t old = *decalsystem;
11174 qboolean useshortelements;
11175 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11176 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11177 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)));
11178 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11179 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11180 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11181 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11182 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11183 if (decalsystem->numdecals)
11184 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11186 Mem_Free(old.decals);
11187 for (i = 0;i < decalsystem->maxdecals*3;i++)
11188 decalsystem->element3i[i] = i;
11189 if (useshortelements)
11190 for (i = 0;i < decalsystem->maxdecals*3;i++)
11191 decalsystem->element3s[i] = i;
11194 // grab a decal and search for another free slot for the next one
11195 decals = decalsystem->decals;
11196 decal = decalsystem->decals + (i = decalsystem->freedecal++);
11197 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11199 decalsystem->freedecal = i;
11200 if (decalsystem->numdecals <= i)
11201 decalsystem->numdecals = i + 1;
11203 // initialize the decal
11205 decal->triangleindex = triangleindex;
11206 decal->surfaceindex = surfaceindex;
11207 decal->decalsequence = decalsequence;
11208 decal->color4f[0][0] = c0[0];
11209 decal->color4f[0][1] = c0[1];
11210 decal->color4f[0][2] = c0[2];
11211 decal->color4f[0][3] = 1;
11212 decal->color4f[1][0] = c1[0];
11213 decal->color4f[1][1] = c1[1];
11214 decal->color4f[1][2] = c1[2];
11215 decal->color4f[1][3] = 1;
11216 decal->color4f[2][0] = c2[0];
11217 decal->color4f[2][1] = c2[1];
11218 decal->color4f[2][2] = c2[2];
11219 decal->color4f[2][3] = 1;
11220 decal->vertex3f[0][0] = v0[0];
11221 decal->vertex3f[0][1] = v0[1];
11222 decal->vertex3f[0][2] = v0[2];
11223 decal->vertex3f[1][0] = v1[0];
11224 decal->vertex3f[1][1] = v1[1];
11225 decal->vertex3f[1][2] = v1[2];
11226 decal->vertex3f[2][0] = v2[0];
11227 decal->vertex3f[2][1] = v2[1];
11228 decal->vertex3f[2][2] = v2[2];
11229 decal->texcoord2f[0][0] = t0[0];
11230 decal->texcoord2f[0][1] = t0[1];
11231 decal->texcoord2f[1][0] = t1[0];
11232 decal->texcoord2f[1][1] = t1[1];
11233 decal->texcoord2f[2][0] = t2[0];
11234 decal->texcoord2f[2][1] = t2[1];
11235 TriangleNormal(v0, v1, v2, decal->plane);
11236 VectorNormalize(decal->plane);
11237 decal->plane[3] = DotProduct(v0, decal->plane);
11240 extern cvar_t cl_decals_bias;
11241 extern cvar_t cl_decals_models;
11242 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11243 // baseparms, parms, temps
11244 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)
11249 const float *vertex3f;
11250 const float *normal3f;
11252 float points[2][9][3];
11259 e = rsurface.modelelement3i + 3*triangleindex;
11261 vertex3f = rsurface.modelvertex3f;
11262 normal3f = rsurface.modelnormal3f;
11266 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11268 index = 3*e[cornerindex];
11269 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11274 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11276 index = 3*e[cornerindex];
11277 VectorCopy(vertex3f + index, v[cornerindex]);
11282 //TriangleNormal(v[0], v[1], v[2], normal);
11283 //if (DotProduct(normal, localnormal) < 0.0f)
11285 // clip by each of the box planes formed from the projection matrix
11286 // if anything survives, we emit the decal
11287 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]);
11290 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]);
11293 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]);
11296 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]);
11299 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]);
11302 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]);
11305 // some part of the triangle survived, so we have to accept it...
11308 // dynamic always uses the original triangle
11310 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11312 index = 3*e[cornerindex];
11313 VectorCopy(vertex3f + index, v[cornerindex]);
11316 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11318 // convert vertex positions to texcoords
11319 Matrix4x4_Transform(projection, v[cornerindex], temp);
11320 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11321 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11322 // calculate distance fade from the projection origin
11323 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11324 f = bound(0.0f, f, 1.0f);
11325 c[cornerindex][0] = r * f;
11326 c[cornerindex][1] = g * f;
11327 c[cornerindex][2] = b * f;
11328 c[cornerindex][3] = 1.0f;
11329 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11332 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);
11334 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11335 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);
11337 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)
11339 matrix4x4_t projection;
11340 decalsystem_t *decalsystem;
11343 const msurface_t *surface;
11344 const msurface_t *surfaces;
11345 const int *surfacelist;
11346 const texture_t *texture;
11348 int numsurfacelist;
11349 int surfacelistindex;
11352 float localorigin[3];
11353 float localnormal[3];
11354 float localmins[3];
11355 float localmaxs[3];
11358 float planes[6][4];
11361 int bih_triangles_count;
11362 int bih_triangles[256];
11363 int bih_surfaces[256];
11365 decalsystem = &ent->decalsystem;
11366 model = ent->model;
11367 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11369 R_DecalSystem_Reset(&ent->decalsystem);
11373 if (!model->brush.data_leafs && !cl_decals_models.integer)
11375 if (decalsystem->model)
11376 R_DecalSystem_Reset(decalsystem);
11380 if (decalsystem->model != model)
11381 R_DecalSystem_Reset(decalsystem);
11382 decalsystem->model = model;
11384 RSurf_ActiveModelEntity(ent, true, false, false);
11386 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11387 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11388 VectorNormalize(localnormal);
11389 localsize = worldsize*rsurface.inversematrixscale;
11390 localmins[0] = localorigin[0] - localsize;
11391 localmins[1] = localorigin[1] - localsize;
11392 localmins[2] = localorigin[2] - localsize;
11393 localmaxs[0] = localorigin[0] + localsize;
11394 localmaxs[1] = localorigin[1] + localsize;
11395 localmaxs[2] = localorigin[2] + localsize;
11397 //VectorCopy(localnormal, planes[4]);
11398 //VectorVectors(planes[4], planes[2], planes[0]);
11399 AnglesFromVectors(angles, localnormal, NULL, false);
11400 AngleVectors(angles, planes[0], planes[2], planes[4]);
11401 VectorNegate(planes[0], planes[1]);
11402 VectorNegate(planes[2], planes[3]);
11403 VectorNegate(planes[4], planes[5]);
11404 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11405 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11406 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11407 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11408 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11409 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11414 matrix4x4_t forwardprojection;
11415 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11416 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11421 float projectionvector[4][3];
11422 VectorScale(planes[0], ilocalsize, projectionvector[0]);
11423 VectorScale(planes[2], ilocalsize, projectionvector[1]);
11424 VectorScale(planes[4], ilocalsize, projectionvector[2]);
11425 projectionvector[0][0] = planes[0][0] * ilocalsize;
11426 projectionvector[0][1] = planes[1][0] * ilocalsize;
11427 projectionvector[0][2] = planes[2][0] * ilocalsize;
11428 projectionvector[1][0] = planes[0][1] * ilocalsize;
11429 projectionvector[1][1] = planes[1][1] * ilocalsize;
11430 projectionvector[1][2] = planes[2][1] * ilocalsize;
11431 projectionvector[2][0] = planes[0][2] * ilocalsize;
11432 projectionvector[2][1] = planes[1][2] * ilocalsize;
11433 projectionvector[2][2] = planes[2][2] * ilocalsize;
11434 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11435 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11436 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11437 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11441 dynamic = model->surfmesh.isanimated;
11442 numsurfacelist = model->nummodelsurfaces;
11443 surfacelist = model->sortedmodelsurfaces;
11444 surfaces = model->data_surfaces;
11447 bih_triangles_count = -1;
11450 if(model->render_bih.numleafs)
11451 bih = &model->render_bih;
11452 else if(model->collision_bih.numleafs)
11453 bih = &model->collision_bih;
11456 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11457 if(bih_triangles_count == 0)
11459 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11461 if(bih_triangles_count > 0)
11463 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11465 surfaceindex = bih_surfaces[triangleindex];
11466 surface = surfaces + surfaceindex;
11467 texture = surface->texture;
11468 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11470 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11472 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11477 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11479 surfaceindex = surfacelist[surfacelistindex];
11480 surface = surfaces + surfaceindex;
11481 // check cull box first because it rejects more than any other check
11482 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11484 // skip transparent surfaces
11485 texture = surface->texture;
11486 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11488 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11490 numtriangles = surface->num_triangles;
11491 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11492 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11497 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11498 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)
11500 int renderentityindex;
11501 float worldmins[3];
11502 float worldmaxs[3];
11503 entity_render_t *ent;
11505 if (!cl_decals_newsystem.integer)
11508 worldmins[0] = worldorigin[0] - worldsize;
11509 worldmins[1] = worldorigin[1] - worldsize;
11510 worldmins[2] = worldorigin[2] - worldsize;
11511 worldmaxs[0] = worldorigin[0] + worldsize;
11512 worldmaxs[1] = worldorigin[1] + worldsize;
11513 worldmaxs[2] = worldorigin[2] + worldsize;
11515 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11517 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11519 ent = r_refdef.scene.entities[renderentityindex];
11520 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11523 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11527 typedef struct r_decalsystem_splatqueue_s
11529 vec3_t worldorigin;
11530 vec3_t worldnormal;
11536 r_decalsystem_splatqueue_t;
11538 int r_decalsystem_numqueued = 0;
11539 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11541 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)
11543 r_decalsystem_splatqueue_t *queue;
11545 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11548 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11549 VectorCopy(worldorigin, queue->worldorigin);
11550 VectorCopy(worldnormal, queue->worldnormal);
11551 Vector4Set(queue->color, r, g, b, a);
11552 Vector4Set(queue->tcrange, s1, t1, s2, t2);
11553 queue->worldsize = worldsize;
11554 queue->decalsequence = cl.decalsequence++;
11557 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11560 r_decalsystem_splatqueue_t *queue;
11562 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11563 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);
11564 r_decalsystem_numqueued = 0;
11567 extern cvar_t cl_decals_max;
11568 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11571 decalsystem_t *decalsystem = &ent->decalsystem;
11578 if (!decalsystem->numdecals)
11581 if (r_showsurfaces.integer)
11584 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11586 R_DecalSystem_Reset(decalsystem);
11590 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11591 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11593 if (decalsystem->lastupdatetime)
11594 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11597 decalsystem->lastupdatetime = r_refdef.scene.time;
11598 numdecals = decalsystem->numdecals;
11600 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11602 if (decal->color4f[0][3])
11604 decal->lived += frametime;
11605 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11607 memset(decal, 0, sizeof(*decal));
11608 if (decalsystem->freedecal > i)
11609 decalsystem->freedecal = i;
11613 decal = decalsystem->decals;
11614 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11617 // collapse the array by shuffling the tail decals into the gaps
11620 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11621 decalsystem->freedecal++;
11622 if (decalsystem->freedecal == numdecals)
11624 decal[decalsystem->freedecal] = decal[--numdecals];
11627 decalsystem->numdecals = numdecals;
11629 if (numdecals <= 0)
11631 // if there are no decals left, reset decalsystem
11632 R_DecalSystem_Reset(decalsystem);
11636 extern skinframe_t *decalskinframe;
11637 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11640 decalsystem_t *decalsystem = &ent->decalsystem;
11649 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11652 numdecals = decalsystem->numdecals;
11656 if (r_showsurfaces.integer)
11659 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11661 R_DecalSystem_Reset(decalsystem);
11665 // if the model is static it doesn't matter what value we give for
11666 // wantnormals and wanttangents, so this logic uses only rules applicable
11667 // to a model, knowing that they are meaningless otherwise
11668 if (ent == r_refdef.scene.worldentity)
11669 RSurf_ActiveWorldEntity();
11671 RSurf_ActiveModelEntity(ent, false, false, false);
11673 decalsystem->lastupdatetime = r_refdef.scene.time;
11675 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11677 // update vertex positions for animated models
11678 v3f = decalsystem->vertex3f;
11679 c4f = decalsystem->color4f;
11680 t2f = decalsystem->texcoord2f;
11681 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11683 if (!decal->color4f[0][3])
11686 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11690 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11693 // update color values for fading decals
11694 if (decal->lived >= cl_decals_time.value)
11695 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11699 c4f[ 0] = decal->color4f[0][0] * alpha;
11700 c4f[ 1] = decal->color4f[0][1] * alpha;
11701 c4f[ 2] = decal->color4f[0][2] * alpha;
11703 c4f[ 4] = decal->color4f[1][0] * alpha;
11704 c4f[ 5] = decal->color4f[1][1] * alpha;
11705 c4f[ 6] = decal->color4f[1][2] * alpha;
11707 c4f[ 8] = decal->color4f[2][0] * alpha;
11708 c4f[ 9] = decal->color4f[2][1] * alpha;
11709 c4f[10] = decal->color4f[2][2] * alpha;
11712 t2f[0] = decal->texcoord2f[0][0];
11713 t2f[1] = decal->texcoord2f[0][1];
11714 t2f[2] = decal->texcoord2f[1][0];
11715 t2f[3] = decal->texcoord2f[1][1];
11716 t2f[4] = decal->texcoord2f[2][0];
11717 t2f[5] = decal->texcoord2f[2][1];
11719 // update vertex positions for animated models
11720 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11722 e = rsurface.modelelement3i + 3*decal->triangleindex;
11723 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11724 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11725 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11729 VectorCopy(decal->vertex3f[0], v3f);
11730 VectorCopy(decal->vertex3f[1], v3f + 3);
11731 VectorCopy(decal->vertex3f[2], v3f + 6);
11734 if (r_refdef.fogenabled)
11736 alpha = RSurf_FogVertex(v3f);
11737 VectorScale(c4f, alpha, c4f);
11738 alpha = RSurf_FogVertex(v3f + 3);
11739 VectorScale(c4f + 4, alpha, c4f + 4);
11740 alpha = RSurf_FogVertex(v3f + 6);
11741 VectorScale(c4f + 8, alpha, c4f + 8);
11752 r_refdef.stats.drawndecals += numtris;
11754 // now render the decals all at once
11755 // (this assumes they all use one particle font texture!)
11756 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);
11757 // R_Mesh_ResetTextureState();
11758 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11759 GL_DepthMask(false);
11760 GL_DepthRange(0, 1);
11761 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11762 GL_DepthTest(true);
11763 GL_CullFace(GL_NONE);
11764 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11765 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
11766 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11770 static void R_DrawModelDecals(void)
11774 // fade faster when there are too many decals
11775 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11776 for (i = 0;i < r_refdef.scene.numentities;i++)
11777 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11779 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11780 for (i = 0;i < r_refdef.scene.numentities;i++)
11781 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11782 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11784 R_DecalSystem_ApplySplatEntitiesQueue();
11786 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11787 for (i = 0;i < r_refdef.scene.numentities;i++)
11788 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11790 r_refdef.stats.totaldecals += numdecals;
11792 if (r_showsurfaces.integer)
11795 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11797 for (i = 0;i < r_refdef.scene.numentities;i++)
11799 if (!r_refdef.viewcache.entityvisible[i])
11801 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11802 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11806 extern cvar_t mod_collision_bih;
11807 static void R_DrawDebugModel(void)
11809 entity_render_t *ent = rsurface.entity;
11810 int i, j, k, l, flagsmask;
11811 const msurface_t *surface;
11812 dp_model_t *model = ent->model;
11815 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11818 if (r_showoverdraw.value > 0)
11820 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11821 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11822 R_SetupShader_Generic_NoTexture(false, false);
11823 GL_DepthTest(false);
11824 GL_DepthMask(false);
11825 GL_DepthRange(0, 1);
11826 GL_BlendFunc(GL_ONE, GL_ONE);
11827 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11829 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11831 rsurface.texture = R_GetCurrentTexture(surface->texture);
11832 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11834 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11835 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11836 if (!rsurface.texture->currentlayers->depthmask)
11837 GL_Color(c, 0, 0, 1.0f);
11838 else if (ent == r_refdef.scene.worldentity)
11839 GL_Color(c, c, c, 1.0f);
11841 GL_Color(0, c, 0, 1.0f);
11842 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11846 rsurface.texture = NULL;
11849 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11851 // R_Mesh_ResetTextureState();
11852 R_SetupShader_Generic_NoTexture(false, false);
11853 GL_DepthRange(0, 1);
11854 GL_DepthTest(!r_showdisabledepthtest.integer);
11855 GL_DepthMask(false);
11856 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11858 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11862 qboolean cullbox = false;
11863 const q3mbrush_t *brush;
11864 const bih_t *bih = &model->collision_bih;
11865 const bih_leaf_t *bihleaf;
11866 float vertex3f[3][3];
11867 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11868 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11870 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11872 switch (bihleaf->type)
11875 brush = model->brush.data_brushes + bihleaf->itemindex;
11876 if (brush->colbrushf && brush->colbrushf->numtriangles)
11878 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);
11879 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11880 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11883 case BIH_COLLISIONTRIANGLE:
11884 triangleindex = bihleaf->itemindex;
11885 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11886 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11887 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11888 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);
11889 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11890 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11892 case BIH_RENDERTRIANGLE:
11893 triangleindex = bihleaf->itemindex;
11894 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11895 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11896 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11897 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);
11898 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11899 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11905 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11908 if (r_showtris.integer && qglPolygonMode)
11910 if (r_showdisabledepthtest.integer)
11912 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11913 GL_DepthMask(false);
11917 GL_BlendFunc(GL_ONE, GL_ZERO);
11918 GL_DepthMask(true);
11920 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11921 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11923 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11925 rsurface.texture = R_GetCurrentTexture(surface->texture);
11926 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11928 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11929 if (!rsurface.texture->currentlayers->depthmask)
11930 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11931 else if (ent == r_refdef.scene.worldentity)
11932 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11934 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11935 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11939 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11940 rsurface.texture = NULL;
11943 if (r_shownormals.value != 0 && qglBegin)
11945 if (r_showdisabledepthtest.integer)
11947 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11948 GL_DepthMask(false);
11952 GL_BlendFunc(GL_ONE, GL_ZERO);
11953 GL_DepthMask(true);
11955 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11957 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11959 rsurface.texture = R_GetCurrentTexture(surface->texture);
11960 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11962 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11963 qglBegin(GL_LINES);
11964 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11966 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11968 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11969 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11970 qglVertex3f(v[0], v[1], v[2]);
11971 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11972 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11973 qglVertex3f(v[0], v[1], v[2]);
11976 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11978 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11980 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11981 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11982 qglVertex3f(v[0], v[1], v[2]);
11983 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11984 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11985 qglVertex3f(v[0], v[1], v[2]);
11988 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11990 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11992 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11993 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11994 qglVertex3f(v[0], v[1], v[2]);
11995 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11996 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11997 qglVertex3f(v[0], v[1], v[2]);
12000 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12002 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12004 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12005 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12006 qglVertex3f(v[0], v[1], v[2]);
12007 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12008 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12009 qglVertex3f(v[0], v[1], v[2]);
12016 rsurface.texture = NULL;
12021 int r_maxsurfacelist = 0;
12022 const msurface_t **r_surfacelist = NULL;
12023 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12025 int i, j, endj, flagsmask;
12026 dp_model_t *model = r_refdef.scene.worldmodel;
12027 msurface_t *surfaces;
12028 unsigned char *update;
12029 int numsurfacelist = 0;
12033 if (r_maxsurfacelist < model->num_surfaces)
12035 r_maxsurfacelist = model->num_surfaces;
12037 Mem_Free((msurface_t**)r_surfacelist);
12038 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12041 RSurf_ActiveWorldEntity();
12043 surfaces = model->data_surfaces;
12044 update = model->brushq1.lightmapupdateflags;
12046 // update light styles on this submodel
12047 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12049 model_brush_lightstyleinfo_t *style;
12050 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12052 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12054 int *list = style->surfacelist;
12055 style->value = r_refdef.scene.lightstylevalue[style->style];
12056 for (j = 0;j < style->numsurfaces;j++)
12057 update[list[j]] = true;
12062 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12066 R_DrawDebugModel();
12067 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12071 rsurface.lightmaptexture = NULL;
12072 rsurface.deluxemaptexture = NULL;
12073 rsurface.uselightmaptexture = false;
12074 rsurface.texture = NULL;
12075 rsurface.rtlight = NULL;
12076 numsurfacelist = 0;
12077 // add visible surfaces to draw list
12078 for (i = 0;i < model->nummodelsurfaces;i++)
12080 j = model->sortedmodelsurfaces[i];
12081 if (r_refdef.viewcache.world_surfacevisible[j])
12082 r_surfacelist[numsurfacelist++] = surfaces + j;
12084 // update lightmaps if needed
12085 if (model->brushq1.firstrender)
12087 model->brushq1.firstrender = false;
12088 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12090 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12094 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12095 if (r_refdef.viewcache.world_surfacevisible[j])
12097 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12099 // don't do anything if there were no surfaces
12100 if (!numsurfacelist)
12102 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12105 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12107 // add to stats if desired
12108 if (r_speeds.integer && !skysurfaces && !depthonly)
12110 r_refdef.stats.world_surfaces += numsurfacelist;
12111 for (j = 0;j < numsurfacelist;j++)
12112 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
12115 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12118 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12120 int i, j, endj, flagsmask;
12121 dp_model_t *model = ent->model;
12122 msurface_t *surfaces;
12123 unsigned char *update;
12124 int numsurfacelist = 0;
12128 if (r_maxsurfacelist < model->num_surfaces)
12130 r_maxsurfacelist = model->num_surfaces;
12132 Mem_Free((msurface_t **)r_surfacelist);
12133 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12136 // if the model is static it doesn't matter what value we give for
12137 // wantnormals and wanttangents, so this logic uses only rules applicable
12138 // to a model, knowing that they are meaningless otherwise
12139 if (ent == r_refdef.scene.worldentity)
12140 RSurf_ActiveWorldEntity();
12141 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12142 RSurf_ActiveModelEntity(ent, false, false, false);
12144 RSurf_ActiveModelEntity(ent, true, true, true);
12145 else if (depthonly)
12147 switch (vid.renderpath)
12149 case RENDERPATH_GL20:
12150 case RENDERPATH_D3D9:
12151 case RENDERPATH_D3D10:
12152 case RENDERPATH_D3D11:
12153 case RENDERPATH_SOFT:
12154 case RENDERPATH_GLES2:
12155 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12157 case RENDERPATH_GL11:
12158 case RENDERPATH_GL13:
12159 case RENDERPATH_GLES1:
12160 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12166 switch (vid.renderpath)
12168 case RENDERPATH_GL20:
12169 case RENDERPATH_D3D9:
12170 case RENDERPATH_D3D10:
12171 case RENDERPATH_D3D11:
12172 case RENDERPATH_SOFT:
12173 case RENDERPATH_GLES2:
12174 RSurf_ActiveModelEntity(ent, true, true, false);
12176 case RENDERPATH_GL11:
12177 case RENDERPATH_GL13:
12178 case RENDERPATH_GLES1:
12179 RSurf_ActiveModelEntity(ent, true, false, false);
12184 surfaces = model->data_surfaces;
12185 update = model->brushq1.lightmapupdateflags;
12187 // update light styles
12188 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12190 model_brush_lightstyleinfo_t *style;
12191 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12193 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12195 int *list = style->surfacelist;
12196 style->value = r_refdef.scene.lightstylevalue[style->style];
12197 for (j = 0;j < style->numsurfaces;j++)
12198 update[list[j]] = true;
12203 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12207 R_DrawDebugModel();
12208 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12212 rsurface.lightmaptexture = NULL;
12213 rsurface.deluxemaptexture = NULL;
12214 rsurface.uselightmaptexture = false;
12215 rsurface.texture = NULL;
12216 rsurface.rtlight = NULL;
12217 numsurfacelist = 0;
12218 // add visible surfaces to draw list
12219 for (i = 0;i < model->nummodelsurfaces;i++)
12220 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12221 // don't do anything if there were no surfaces
12222 if (!numsurfacelist)
12224 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12227 // update lightmaps if needed
12231 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12236 R_BuildLightMap(ent, surfaces + j);
12241 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12243 // add to stats if desired
12244 if (r_speeds.integer && !skysurfaces && !depthonly)
12246 r_refdef.stats.entities_surfaces += numsurfacelist;
12247 for (j = 0;j < numsurfacelist;j++)
12248 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
12251 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12254 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12256 static texture_t texture;
12257 static msurface_t surface;
12258 const msurface_t *surfacelist = &surface;
12260 // fake enough texture and surface state to render this geometry
12262 texture.update_lastrenderframe = -1; // regenerate this texture
12263 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12264 texture.currentskinframe = skinframe;
12265 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12266 texture.offsetmapping = OFFSETMAPPING_OFF;
12267 texture.offsetscale = 1;
12268 texture.specularscalemod = 1;
12269 texture.specularpowermod = 1;
12270 texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12271 // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12272 // JUST GREP FOR "specularscalemod = 1".
12274 surface.texture = &texture;
12275 surface.num_triangles = numtriangles;
12276 surface.num_firsttriangle = firsttriangle;
12277 surface.num_vertices = numvertices;
12278 surface.num_firstvertex = firstvertex;
12281 rsurface.texture = R_GetCurrentTexture(surface.texture);
12282 rsurface.lightmaptexture = NULL;
12283 rsurface.deluxemaptexture = NULL;
12284 rsurface.uselightmaptexture = false;
12285 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12288 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)
12290 static msurface_t surface;
12291 const msurface_t *surfacelist = &surface;
12293 // fake enough texture and surface state to render this geometry
12294 surface.texture = texture;
12295 surface.num_triangles = numtriangles;
12296 surface.num_firsttriangle = firsttriangle;
12297 surface.num_vertices = numvertices;
12298 surface.num_firstvertex = firstvertex;
12301 rsurface.texture = R_GetCurrentTexture(surface.texture);
12302 rsurface.lightmaptexture = NULL;
12303 rsurface.deluxemaptexture = NULL;
12304 rsurface.uselightmaptexture = false;
12305 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);