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;
47 static qboolean r_gpuskeletal;
54 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!"};
55 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!"};
56 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
57 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
58 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)"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
60 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"};
61 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"};
62 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"};
63 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"};
64 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"};
65 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"};
67 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
68 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"};
69 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
70 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)"};
71 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
73 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"};
74 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
75 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
76 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
77 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
78 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
79 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
80 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"};
81 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"};
82 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"};
83 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
84 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
85 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)"};
86 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
87 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
88 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"};
89 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"};
90 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
91 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"};
92 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"};
93 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"};
94 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
95 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
96 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
97 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
98 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
99 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
100 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
101 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)"};
102 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)"};
103 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
104 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
105 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
106 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
107 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
109 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
110 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
111 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
113 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
114 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
115 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
116 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."};
117 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
118 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
119 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
120 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."};
121 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
122 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
123 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
124 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."};
125 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
126 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"};
127 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"};
128 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
129 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
130 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
131 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
132 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
133 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"};
134 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
135 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
136 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
137 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
138 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
140 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
141 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
142 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
143 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
144 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
145 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
146 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
147 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
149 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)"};
150 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"};
152 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
153 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
154 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
156 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"};
157 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"};
158 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"};
159 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
160 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
161 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"};
162 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)"};
163 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)"};
164 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
166 cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
167 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)"};
168 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
169 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)"};
170 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
171 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)"};
172 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)"};
173 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
174 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"};
175 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."};
176 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
177 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)"};
178 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)"};
179 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)"};
180 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)"};
181 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)"};
182 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)"};
183 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)"};
184 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)"};
186 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)"};
187 cvar_t r_water_cameraentitiesonly = {CVAR_SAVE, "r_water_cameraentitiesonly", "0", "whether to only show QC-defined reflections/refractions (typically used for camera- or portal-like effects)"};
188 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
189 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"};
190 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
191 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
192 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
193 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"};
194 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"};
195 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)"};
197 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
198 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
199 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
200 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
202 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
203 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
205 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
206 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
207 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
208 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
209 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
210 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
212 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
213 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
214 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
215 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
216 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
217 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
218 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
219 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
220 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
221 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
223 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"};
225 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"};
227 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
229 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
231 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)"};
232 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)"};
233 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
234 cvar_t r_batch_dynamicbuffer = {CVAR_SAVE, "r_batch_dynamicbuffer", "0", "use vertex/index buffers for drawing dynamic and copytriangles batches"};
236 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
237 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"};
239 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."};
241 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)"};
242 cvar_t r_buffermegs[R_BUFFERDATA_COUNT] =
244 {CVAR_SAVE, "r_buffermegs_vertex", "4", "vertex buffer size for one frame"},
245 {CVAR_SAVE, "r_buffermegs_index16", "1", "index buffer size for one frame (16bit indices)"},
246 {CVAR_SAVE, "r_buffermegs_index32", "1", "index buffer size for one frame (32bit indices)"},
247 {CVAR_SAVE, "r_buffermegs_uniform", "0.25", "uniform buffer size for one frame"},
250 extern cvar_t v_glslgamma;
251 extern cvar_t v_glslgamma_2d;
253 extern qboolean v_flipped_state;
255 r_framebufferstate_t r_fb;
257 /// shadow volume bsp struct with automatically growing nodes buffer
260 int r_uniformbufferalignment = 32; // dynamically updated to match GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
262 rtexture_t *r_texture_blanknormalmap;
263 rtexture_t *r_texture_white;
264 rtexture_t *r_texture_grey128;
265 rtexture_t *r_texture_black;
266 rtexture_t *r_texture_notexture;
267 rtexture_t *r_texture_whitecube;
268 rtexture_t *r_texture_normalizationcube;
269 rtexture_t *r_texture_fogattenuation;
270 rtexture_t *r_texture_fogheighttexture;
271 rtexture_t *r_texture_gammaramps;
272 unsigned int r_texture_gammaramps_serial;
273 //rtexture_t *r_texture_fogintensity;
274 rtexture_t *r_texture_reflectcube;
276 // TODO: hash lookups?
277 typedef struct cubemapinfo_s
284 int r_texture_numcubemaps;
285 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
287 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
288 unsigned int r_numqueries;
289 unsigned int r_maxqueries;
291 typedef struct r_qwskincache_s
293 char name[MAX_QPATH];
294 skinframe_t *skinframe;
298 static r_qwskincache_t *r_qwskincache;
299 static int r_qwskincache_size;
301 /// vertex coordinates for a quad that covers the screen exactly
302 extern const float r_screenvertex3f[12];
303 extern const float r_d3dscreenvertex3f[12];
304 const float r_screenvertex3f[12] =
311 const float r_d3dscreenvertex3f[12] =
319 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
322 for (i = 0;i < verts;i++)
333 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
336 for (i = 0;i < verts;i++)
346 // FIXME: move this to client?
349 if (gamemode == GAME_NEHAHRA)
351 Cvar_Set("gl_fogenable", "0");
352 Cvar_Set("gl_fogdensity", "0.2");
353 Cvar_Set("gl_fogred", "0.3");
354 Cvar_Set("gl_foggreen", "0.3");
355 Cvar_Set("gl_fogblue", "0.3");
357 r_refdef.fog_density = 0;
358 r_refdef.fog_red = 0;
359 r_refdef.fog_green = 0;
360 r_refdef.fog_blue = 0;
361 r_refdef.fog_alpha = 1;
362 r_refdef.fog_start = 0;
363 r_refdef.fog_end = 16384;
364 r_refdef.fog_height = 1<<30;
365 r_refdef.fog_fadedepth = 128;
366 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
369 static void R_BuildBlankTextures(void)
371 unsigned char data[4];
372 data[2] = 128; // normal X
373 data[1] = 128; // normal Y
374 data[0] = 255; // normal Z
375 data[3] = 255; // height
376 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
381 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
386 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
391 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
394 static void R_BuildNoTexture(void)
397 unsigned char pix[16][16][4];
398 // this makes a light grey/dark grey checkerboard texture
399 for (y = 0;y < 16;y++)
401 for (x = 0;x < 16;x++)
403 if ((y < 8) ^ (x < 8))
419 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
422 static void R_BuildWhiteCube(void)
424 unsigned char data[6*1*1*4];
425 memset(data, 255, sizeof(data));
426 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
429 static void R_BuildNormalizationCube(void)
433 vec_t s, t, intensity;
436 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
437 for (side = 0;side < 6;side++)
439 for (y = 0;y < NORMSIZE;y++)
441 for (x = 0;x < NORMSIZE;x++)
443 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
444 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
479 intensity = 127.0f / sqrt(DotProduct(v, v));
480 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
481 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
482 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
483 data[((side*64+y)*64+x)*4+3] = 255;
487 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
491 static void R_BuildFogTexture(void)
495 unsigned char data1[FOGWIDTH][4];
496 //unsigned char data2[FOGWIDTH][4];
499 r_refdef.fogmasktable_start = r_refdef.fog_start;
500 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
501 r_refdef.fogmasktable_range = r_refdef.fogrange;
502 r_refdef.fogmasktable_density = r_refdef.fog_density;
504 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
505 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
507 d = (x * r - r_refdef.fogmasktable_start);
508 if(developer_extra.integer)
509 Con_DPrintf("%f ", d);
511 if (r_fog_exp2.integer)
512 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
514 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
515 if(developer_extra.integer)
516 Con_DPrintf(" : %f ", alpha);
517 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
518 if(developer_extra.integer)
519 Con_DPrintf(" = %f\n", alpha);
520 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
523 for (x = 0;x < FOGWIDTH;x++)
525 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
530 //data2[x][0] = 255 - b;
531 //data2[x][1] = 255 - b;
532 //data2[x][2] = 255 - b;
535 if (r_texture_fogattenuation)
537 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
538 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
542 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
543 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
547 static void R_BuildFogHeightTexture(void)
549 unsigned char *inpixels;
557 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
558 if (r_refdef.fogheighttexturename[0])
559 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
562 r_refdef.fog_height_tablesize = 0;
563 if (r_texture_fogheighttexture)
564 R_FreeTexture(r_texture_fogheighttexture);
565 r_texture_fogheighttexture = NULL;
566 if (r_refdef.fog_height_table2d)
567 Mem_Free(r_refdef.fog_height_table2d);
568 r_refdef.fog_height_table2d = NULL;
569 if (r_refdef.fog_height_table1d)
570 Mem_Free(r_refdef.fog_height_table1d);
571 r_refdef.fog_height_table1d = NULL;
575 r_refdef.fog_height_tablesize = size;
576 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
577 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
578 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
580 // LordHavoc: now the magic - what is that table2d for? it is a cooked
581 // average fog color table accounting for every fog layer between a point
582 // and the camera. (Note: attenuation is handled separately!)
583 for (y = 0;y < size;y++)
585 for (x = 0;x < size;x++)
591 for (j = x;j <= y;j++)
593 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
599 for (j = x;j >= y;j--)
601 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
606 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
607 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
608 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
609 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
612 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
615 //=======================================================================================================================================================
617 static const char *builtinshaderstrings[] =
619 #include "shader_glsl.h"
623 const char *builtinhlslshaderstrings[] =
625 #include "shader_hlsl.h"
629 char *glslshaderstring = NULL;
630 char *hlslshaderstring = NULL;
632 //=======================================================================================================================================================
634 typedef struct shaderpermutationinfo_s
639 shaderpermutationinfo_t;
641 typedef struct shadermodeinfo_s
643 const char *filename;
649 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
650 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
652 {"#define USEDIFFUSE\n", " diffuse"},
653 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
654 {"#define USEVIEWTINT\n", " viewtint"},
655 {"#define USECOLORMAPPING\n", " colormapping"},
656 {"#define USESATURATION\n", " saturation"},
657 {"#define USEFOGINSIDE\n", " foginside"},
658 {"#define USEFOGOUTSIDE\n", " fogoutside"},
659 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
660 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
661 {"#define USEGAMMARAMPS\n", " gammaramps"},
662 {"#define USECUBEFILTER\n", " cubefilter"},
663 {"#define USEGLOW\n", " glow"},
664 {"#define USEBLOOM\n", " bloom"},
665 {"#define USESPECULAR\n", " specular"},
666 {"#define USEPOSTPROCESSING\n", " postprocessing"},
667 {"#define USEREFLECTION\n", " reflection"},
668 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
669 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
670 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
671 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
672 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
673 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
674 {"#define USEALPHAKILL\n", " alphakill"},
675 {"#define USEREFLECTCUBE\n", " reflectcube"},
676 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
677 {"#define USEBOUNCEGRID\n", " bouncegrid"},
678 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
679 {"#define USETRIPPY\n", " trippy"},
680 {"#define USEDEPTHRGB\n", " depthrgb"},
681 {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
682 {"#define USESKELETAL\n", " skeletal"},
683 {"#define USEOCCLUDE\n", " occlude"}
686 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
687 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
689 {"glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
690 {"glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
691 {"glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
692 {"glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
693 {"glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
694 {"glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
695 {"glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
696 {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
697 {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
698 {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
699 {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
700 {"glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
701 {"glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
702 {"glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
703 {"glsl/default.glsl", "#define MODE_WATER\n", " water"},
704 {"glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
705 {"glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
708 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
710 {"hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
711 {"hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
712 {"hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
713 {"hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
714 {"hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
715 {"hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
716 {"hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
717 {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
718 {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
719 {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
720 {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
721 {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
722 {"hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
723 {"hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
724 {"hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
725 {"hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
726 {"hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
729 struct r_glsl_permutation_s;
730 typedef struct r_glsl_permutation_s
733 struct r_glsl_permutation_s *hashnext;
735 unsigned int permutation;
737 /// indicates if we have tried compiling this permutation already
739 /// 0 if compilation failed
741 // texture units assigned to each detected uniform
742 int tex_Texture_First;
743 int tex_Texture_Second;
744 int tex_Texture_GammaRamps;
745 int tex_Texture_Normal;
746 int tex_Texture_Color;
747 int tex_Texture_Gloss;
748 int tex_Texture_Glow;
749 int tex_Texture_SecondaryNormal;
750 int tex_Texture_SecondaryColor;
751 int tex_Texture_SecondaryGloss;
752 int tex_Texture_SecondaryGlow;
753 int tex_Texture_Pants;
754 int tex_Texture_Shirt;
755 int tex_Texture_FogHeightTexture;
756 int tex_Texture_FogMask;
757 int tex_Texture_Lightmap;
758 int tex_Texture_Deluxemap;
759 int tex_Texture_Attenuation;
760 int tex_Texture_Cube;
761 int tex_Texture_Refraction;
762 int tex_Texture_Reflection;
763 int tex_Texture_ShadowMap2D;
764 int tex_Texture_CubeProjection;
765 int tex_Texture_ScreenNormalMap;
766 int tex_Texture_ScreenDiffuse;
767 int tex_Texture_ScreenSpecular;
768 int tex_Texture_ReflectMask;
769 int tex_Texture_ReflectCube;
770 int tex_Texture_BounceGrid;
771 /// locations of detected uniforms in program object, or -1 if not found
772 int loc_Texture_First;
773 int loc_Texture_Second;
774 int loc_Texture_GammaRamps;
775 int loc_Texture_Normal;
776 int loc_Texture_Color;
777 int loc_Texture_Gloss;
778 int loc_Texture_Glow;
779 int loc_Texture_SecondaryNormal;
780 int loc_Texture_SecondaryColor;
781 int loc_Texture_SecondaryGloss;
782 int loc_Texture_SecondaryGlow;
783 int loc_Texture_Pants;
784 int loc_Texture_Shirt;
785 int loc_Texture_FogHeightTexture;
786 int loc_Texture_FogMask;
787 int loc_Texture_Lightmap;
788 int loc_Texture_Deluxemap;
789 int loc_Texture_Attenuation;
790 int loc_Texture_Cube;
791 int loc_Texture_Refraction;
792 int loc_Texture_Reflection;
793 int loc_Texture_ShadowMap2D;
794 int loc_Texture_CubeProjection;
795 int loc_Texture_ScreenNormalMap;
796 int loc_Texture_ScreenDiffuse;
797 int loc_Texture_ScreenSpecular;
798 int loc_Texture_ReflectMask;
799 int loc_Texture_ReflectCube;
800 int loc_Texture_BounceGrid;
802 int loc_BloomBlur_Parameters;
804 int loc_Color_Ambient;
805 int loc_Color_Diffuse;
806 int loc_Color_Specular;
810 int loc_DeferredColor_Ambient;
811 int loc_DeferredColor_Diffuse;
812 int loc_DeferredColor_Specular;
813 int loc_DeferredMod_Diffuse;
814 int loc_DeferredMod_Specular;
815 int loc_DistortScaleRefractReflect;
818 int loc_FogHeightFade;
820 int loc_FogPlaneViewDist;
821 int loc_FogRangeRecip;
824 int loc_LightPosition;
825 int loc_OffsetMapping_ScaleSteps;
826 int loc_OffsetMapping_LodDistance;
827 int loc_OffsetMapping_Bias;
829 int loc_ReflectColor;
830 int loc_ReflectFactor;
831 int loc_ReflectOffset;
832 int loc_RefractColor;
834 int loc_ScreenCenterRefractReflect;
835 int loc_ScreenScaleRefractReflect;
836 int loc_ScreenToDepth;
837 int loc_ShadowMap_Parameters;
838 int loc_ShadowMap_TextureScale;
839 int loc_SpecularPower;
840 int loc_Skeletal_Transform12;
845 int loc_ViewTintColor;
847 int loc_ModelToLight;
849 int loc_BackgroundTexMatrix;
850 int loc_ModelViewProjectionMatrix;
851 int loc_ModelViewMatrix;
852 int loc_PixelToScreenTexCoord;
853 int loc_ModelToReflectCube;
854 int loc_ShadowMapMatrix;
855 int loc_BloomColorSubtract;
856 int loc_NormalmapScrollBlend;
857 int loc_BounceGridMatrix;
858 int loc_BounceGridIntensity;
859 /// uniform block bindings
860 int ubibind_Skeletal_Transform12_UniformBlock;
861 /// uniform block indices
862 int ubiloc_Skeletal_Transform12_UniformBlock;
864 r_glsl_permutation_t;
866 #define SHADERPERMUTATION_HASHSIZE 256
869 // non-degradable "lightweight" shader parameters to keep the permutations simpler
870 // these can NOT degrade! only use for simple stuff
873 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
874 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
875 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
876 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
877 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
878 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
879 SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
880 SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7, ///< LOD for offsetmapping
881 SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
882 SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
883 SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
884 SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
885 SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
886 SHADERSTATICPARM_FXAA = 13 ///< fast approximate anti aliasing
888 #define SHADERSTATICPARMS_COUNT 14
890 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
891 static int shaderstaticparms_count = 0;
893 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
894 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
896 extern qboolean r_shadow_shadowmapsampler;
897 extern int r_shadow_shadowmappcf;
898 qboolean R_CompileShader_CheckStaticParms(void)
900 static int r_compileshader_staticparms_save[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5];
901 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
902 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
905 if (r_glsl_saturation_redcompensate.integer)
906 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
907 if (r_glsl_vertextextureblend_usebothalphas.integer)
908 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
909 if (r_shadow_glossexact.integer)
910 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
911 if (r_glsl_postprocess.integer)
913 if (r_glsl_postprocess_uservec1_enable.integer)
914 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
915 if (r_glsl_postprocess_uservec2_enable.integer)
916 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
917 if (r_glsl_postprocess_uservec3_enable.integer)
918 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
919 if (r_glsl_postprocess_uservec4_enable.integer)
920 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
923 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_FXAA);
924 if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
925 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
927 if (r_shadow_shadowmapsampler)
928 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
929 if (r_shadow_shadowmappcf > 1)
930 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
931 else if (r_shadow_shadowmappcf)
932 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
933 if (r_celshading.integer)
934 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
935 if (r_celoutlines.integer)
936 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
938 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
941 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
942 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
943 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
945 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
946 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
948 shaderstaticparms_count = 0;
951 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
952 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
953 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
954 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
955 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
956 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
957 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
958 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
959 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
960 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
961 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
962 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
963 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
964 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_FXAA, "USEFXAA");
967 /// information about each possible shader permutation
968 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
969 /// currently selected permutation
970 r_glsl_permutation_t *r_glsl_permutation;
971 /// storage for permutations linked in the hash table
972 memexpandablearray_t r_glsl_permutationarray;
974 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
976 //unsigned int hashdepth = 0;
977 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
978 r_glsl_permutation_t *p;
979 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
981 if (p->mode == mode && p->permutation == permutation)
983 //if (hashdepth > 10)
984 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
989 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
991 p->permutation = permutation;
992 p->hashnext = r_glsl_permutationhash[mode][hashindex];
993 r_glsl_permutationhash[mode][hashindex] = p;
994 //if (hashdepth > 10)
995 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
999 static char *R_ShaderStrCat(const char **strings)
1002 const char **p = strings;
1005 for (p = strings;(t = *p);p++)
1008 s = string = (char *)Mem_Alloc(r_main_mempool, len);
1010 for (p = strings;(t = *p);p++)
1020 static char *R_GetShaderText(const char *filename, qboolean printfromdisknotice, qboolean builtinonly)
1023 if (!filename || !filename[0])
1025 // LordHavoc: note that FS_LoadFile appends a 0 byte to make it a valid string, so does R_ShaderStrCat
1026 if (!strcmp(filename, "glsl/default.glsl"))
1029 return R_ShaderStrCat(builtinshaderstrings);
1030 if (!glslshaderstring)
1032 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1033 if (glslshaderstring)
1034 Con_DPrintf("Loading shaders from file %s...\n", filename);
1036 glslshaderstring = R_ShaderStrCat(builtinshaderstrings);
1038 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
1039 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
1040 return shaderstring;
1042 if (!strcmp(filename, "hlsl/default.hlsl"))
1045 return R_ShaderStrCat(builtinhlslshaderstrings);
1046 if (!hlslshaderstring)
1048 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1049 if (hlslshaderstring)
1050 Con_DPrintf("Loading shaders from file %s...\n", filename);
1052 hlslshaderstring = R_ShaderStrCat(builtinhlslshaderstrings);
1054 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1055 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1056 return shaderstring;
1058 // we don't have builtin strings for any other files
1061 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1064 if (printfromdisknotice)
1065 Con_DPrintf("from disk %s... ", filename);
1066 return shaderstring;
1068 return shaderstring;
1071 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1076 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1078 char permutationname[256];
1079 int vertstrings_count = 0;
1080 int geomstrings_count = 0;
1081 int fragstrings_count = 0;
1082 const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1083 const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1084 const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1091 permutationname[0] = 0;
1092 sourcestring = R_GetShaderText(modeinfo->filename, true, false);
1094 strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1096 // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1097 if(vid.support.glshaderversion >= 140)
1099 vertstrings_list[vertstrings_count++] = "#version 140\n";
1100 geomstrings_list[geomstrings_count++] = "#version 140\n";
1101 fragstrings_list[fragstrings_count++] = "#version 140\n";
1102 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1103 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1104 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1106 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1107 else if(vid.support.glshaderversion >= 130)
1109 vertstrings_list[vertstrings_count++] = "#version 130\n";
1110 geomstrings_list[geomstrings_count++] = "#version 130\n";
1111 fragstrings_list[fragstrings_count++] = "#version 130\n";
1112 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1113 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1114 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1117 // the first pretext is which type of shader to compile as
1118 // (later these will all be bound together as a program object)
1119 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1120 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1121 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1123 // the second pretext is the mode (for example a light source)
1124 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1125 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1126 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1127 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1129 // now add all the permutation pretexts
1130 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1132 if (permutation & (1<<i))
1134 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1135 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1136 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1137 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1141 // keep line numbers correct
1142 vertstrings_list[vertstrings_count++] = "\n";
1143 geomstrings_list[geomstrings_count++] = "\n";
1144 fragstrings_list[fragstrings_count++] = "\n";
1149 R_CompileShader_AddStaticParms(mode, permutation);
1150 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1151 vertstrings_count += shaderstaticparms_count;
1152 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1153 geomstrings_count += shaderstaticparms_count;
1154 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1155 fragstrings_count += shaderstaticparms_count;
1157 // now append the shader text itself
1158 vertstrings_list[vertstrings_count++] = sourcestring;
1159 geomstrings_list[geomstrings_count++] = sourcestring;
1160 fragstrings_list[fragstrings_count++] = sourcestring;
1162 // compile the shader program
1163 if (vertstrings_count + geomstrings_count + fragstrings_count)
1164 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1168 qglUseProgram(p->program);CHECKGLERROR
1169 // look up all the uniform variable names we care about, so we don't
1170 // have to look them up every time we set them
1175 GLint activeuniformindex = 0;
1176 GLint numactiveuniforms = 0;
1177 char uniformname[128];
1178 GLsizei uniformnamelength = 0;
1179 GLint uniformsize = 0;
1180 GLenum uniformtype = 0;
1181 memset(uniformname, 0, sizeof(uniformname));
1182 qglGetProgramiv(p->program, GL_ACTIVE_UNIFORMS, &numactiveuniforms);
1183 Con_Printf("Shader has %i uniforms\n", numactiveuniforms);
1184 for (activeuniformindex = 0;activeuniformindex < numactiveuniforms;activeuniformindex++)
1186 qglGetActiveUniform(p->program, activeuniformindex, sizeof(uniformname) - 1, &uniformnamelength, &uniformsize, &uniformtype, uniformname);
1187 Con_Printf("Uniform %i name \"%s\" size %i type %i\n", (int)activeuniformindex, uniformname, (int)uniformsize, (int)uniformtype);
1192 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1193 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1194 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1195 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1196 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1197 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1198 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1199 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1200 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1201 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1202 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1203 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1204 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1205 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1206 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1207 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1208 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1209 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1210 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1211 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1212 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1213 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1214 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1215 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1216 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1217 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1218 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1219 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1220 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1221 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1222 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1223 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1224 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1225 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1226 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1227 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1228 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1229 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1230 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1231 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1232 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1233 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1234 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1235 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1236 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1237 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1238 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1239 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1240 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1241 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1242 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1243 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1244 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1245 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1246 p->loc_OffsetMapping_LodDistance = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1247 p->loc_OffsetMapping_Bias = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1248 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1249 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1250 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1251 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1252 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1253 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1254 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1255 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1256 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1257 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1258 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1259 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1260 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1261 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1262 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1263 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1264 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1265 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1266 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1267 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1268 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1269 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1270 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1271 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1272 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1273 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1274 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1275 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1276 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1277 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1278 // initialize the samplers to refer to the texture units we use
1279 p->tex_Texture_First = -1;
1280 p->tex_Texture_Second = -1;
1281 p->tex_Texture_GammaRamps = -1;
1282 p->tex_Texture_Normal = -1;
1283 p->tex_Texture_Color = -1;
1284 p->tex_Texture_Gloss = -1;
1285 p->tex_Texture_Glow = -1;
1286 p->tex_Texture_SecondaryNormal = -1;
1287 p->tex_Texture_SecondaryColor = -1;
1288 p->tex_Texture_SecondaryGloss = -1;
1289 p->tex_Texture_SecondaryGlow = -1;
1290 p->tex_Texture_Pants = -1;
1291 p->tex_Texture_Shirt = -1;
1292 p->tex_Texture_FogHeightTexture = -1;
1293 p->tex_Texture_FogMask = -1;
1294 p->tex_Texture_Lightmap = -1;
1295 p->tex_Texture_Deluxemap = -1;
1296 p->tex_Texture_Attenuation = -1;
1297 p->tex_Texture_Cube = -1;
1298 p->tex_Texture_Refraction = -1;
1299 p->tex_Texture_Reflection = -1;
1300 p->tex_Texture_ShadowMap2D = -1;
1301 p->tex_Texture_CubeProjection = -1;
1302 p->tex_Texture_ScreenNormalMap = -1;
1303 p->tex_Texture_ScreenDiffuse = -1;
1304 p->tex_Texture_ScreenSpecular = -1;
1305 p->tex_Texture_ReflectMask = -1;
1306 p->tex_Texture_ReflectCube = -1;
1307 p->tex_Texture_BounceGrid = -1;
1308 // bind the texture samplers in use
1310 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1311 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1312 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1313 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1314 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1315 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1316 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1317 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1318 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1319 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1320 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1321 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1322 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1323 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1324 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1325 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1326 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1327 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1328 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1329 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1330 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1331 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1332 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1333 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1334 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1335 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1336 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1337 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1338 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1339 // get the uniform block indices so we can bind them
1340 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1341 if (vid.support.arb_uniform_buffer_object)
1342 p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1345 p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1346 // clear the uniform block bindings
1347 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1348 // bind the uniform blocks in use
1350 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1351 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1353 // we're done compiling and setting up the shader, at least until it is used
1355 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1358 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1362 Mem_Free(sourcestring);
1365 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1367 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1368 if (r_glsl_permutation != perm)
1370 r_glsl_permutation = perm;
1371 if (!r_glsl_permutation->program)
1373 if (!r_glsl_permutation->compiled)
1375 Con_DPrintf("Compiling shader mode %u permutation %u\n", mode, permutation);
1376 R_GLSL_CompilePermutation(perm, mode, permutation);
1378 if (!r_glsl_permutation->program)
1380 // remove features until we find a valid permutation
1382 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1384 // reduce i more quickly whenever it would not remove any bits
1385 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1386 if (!(permutation & j))
1389 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1390 if (!r_glsl_permutation->compiled)
1391 R_GLSL_CompilePermutation(perm, mode, permutation);
1392 if (r_glsl_permutation->program)
1395 if (i >= SHADERPERMUTATION_COUNT)
1397 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1398 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1399 qglUseProgram(0);CHECKGLERROR
1400 return; // no bit left to clear, entire mode is broken
1405 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1407 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1408 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1409 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1417 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1418 extern D3DCAPS9 vid_d3d9caps;
1421 struct r_hlsl_permutation_s;
1422 typedef struct r_hlsl_permutation_s
1424 /// hash lookup data
1425 struct r_hlsl_permutation_s *hashnext;
1427 unsigned int permutation;
1429 /// indicates if we have tried compiling this permutation already
1431 /// NULL if compilation failed
1432 IDirect3DVertexShader9 *vertexshader;
1433 IDirect3DPixelShader9 *pixelshader;
1435 r_hlsl_permutation_t;
1437 typedef enum D3DVSREGISTER_e
1439 D3DVSREGISTER_TexMatrix = 0, // float4x4
1440 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1441 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1442 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1443 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1444 D3DVSREGISTER_ModelToLight = 20, // float4x4
1445 D3DVSREGISTER_EyePosition = 24,
1446 D3DVSREGISTER_FogPlane = 25,
1447 D3DVSREGISTER_LightDir = 26,
1448 D3DVSREGISTER_LightPosition = 27,
1452 typedef enum D3DPSREGISTER_e
1454 D3DPSREGISTER_Alpha = 0,
1455 D3DPSREGISTER_BloomBlur_Parameters = 1,
1456 D3DPSREGISTER_ClientTime = 2,
1457 D3DPSREGISTER_Color_Ambient = 3,
1458 D3DPSREGISTER_Color_Diffuse = 4,
1459 D3DPSREGISTER_Color_Specular = 5,
1460 D3DPSREGISTER_Color_Glow = 6,
1461 D3DPSREGISTER_Color_Pants = 7,
1462 D3DPSREGISTER_Color_Shirt = 8,
1463 D3DPSREGISTER_DeferredColor_Ambient = 9,
1464 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1465 D3DPSREGISTER_DeferredColor_Specular = 11,
1466 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1467 D3DPSREGISTER_DeferredMod_Specular = 13,
1468 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1469 D3DPSREGISTER_EyePosition = 15, // unused
1470 D3DPSREGISTER_FogColor = 16,
1471 D3DPSREGISTER_FogHeightFade = 17,
1472 D3DPSREGISTER_FogPlane = 18,
1473 D3DPSREGISTER_FogPlaneViewDist = 19,
1474 D3DPSREGISTER_FogRangeRecip = 20,
1475 D3DPSREGISTER_LightColor = 21,
1476 D3DPSREGISTER_LightDir = 22, // unused
1477 D3DPSREGISTER_LightPosition = 23,
1478 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1479 D3DPSREGISTER_PixelSize = 25,
1480 D3DPSREGISTER_ReflectColor = 26,
1481 D3DPSREGISTER_ReflectFactor = 27,
1482 D3DPSREGISTER_ReflectOffset = 28,
1483 D3DPSREGISTER_RefractColor = 29,
1484 D3DPSREGISTER_Saturation = 30,
1485 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1486 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1487 D3DPSREGISTER_ScreenToDepth = 33,
1488 D3DPSREGISTER_ShadowMap_Parameters = 34,
1489 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1490 D3DPSREGISTER_SpecularPower = 36,
1491 D3DPSREGISTER_UserVec1 = 37,
1492 D3DPSREGISTER_UserVec2 = 38,
1493 D3DPSREGISTER_UserVec3 = 39,
1494 D3DPSREGISTER_UserVec4 = 40,
1495 D3DPSREGISTER_ViewTintColor = 41,
1496 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1497 D3DPSREGISTER_BloomColorSubtract = 43,
1498 D3DPSREGISTER_ViewToLight = 44, // float4x4
1499 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1500 D3DPSREGISTER_NormalmapScrollBlend = 52,
1501 D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1502 D3DPSREGISTER_OffsetMapping_Bias = 54,
1507 /// information about each possible shader permutation
1508 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1509 /// currently selected permutation
1510 r_hlsl_permutation_t *r_hlsl_permutation;
1511 /// storage for permutations linked in the hash table
1512 memexpandablearray_t r_hlsl_permutationarray;
1514 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1516 //unsigned int hashdepth = 0;
1517 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1518 r_hlsl_permutation_t *p;
1519 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1521 if (p->mode == mode && p->permutation == permutation)
1523 //if (hashdepth > 10)
1524 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1529 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1531 p->permutation = permutation;
1532 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1533 r_hlsl_permutationhash[mode][hashindex] = p;
1534 //if (hashdepth > 10)
1535 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1540 //#include <d3dx9shader.h>
1541 //#include <d3dx9mesh.h>
1543 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1545 DWORD *vsbin = NULL;
1546 DWORD *psbin = NULL;
1547 fs_offset_t vsbinsize;
1548 fs_offset_t psbinsize;
1549 // IDirect3DVertexShader9 *vs = NULL;
1550 // IDirect3DPixelShader9 *ps = NULL;
1551 ID3DXBuffer *vslog = NULL;
1552 ID3DXBuffer *vsbuffer = NULL;
1553 ID3DXConstantTable *vsconstanttable = NULL;
1554 ID3DXBuffer *pslog = NULL;
1555 ID3DXBuffer *psbuffer = NULL;
1556 ID3DXConstantTable *psconstanttable = NULL;
1559 char temp[MAX_INPUTLINE];
1560 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1562 qboolean debugshader = gl_paranoid.integer != 0;
1563 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1564 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1567 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1568 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1570 if ((!vsbin && vertstring) || (!psbin && fragstring))
1572 const char* dllnames_d3dx9 [] =
1596 dllhandle_t d3dx9_dll = NULL;
1597 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1598 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1599 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1600 dllfunction_t d3dx9_dllfuncs[] =
1602 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1603 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1604 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1607 // LordHavoc: the June 2010 SDK lacks these macros to make ID3DXBuffer usable in C, and to make it work in both C and C++ the macros are needed...
1608 #ifndef ID3DXBuffer_GetBufferPointer
1609 #if !defined(__cplusplus) || defined(CINTERFACE)
1610 #define ID3DXBuffer_GetBufferPointer(p) (p)->lpVtbl->GetBufferPointer(p)
1611 #define ID3DXBuffer_GetBufferSize(p) (p)->lpVtbl->GetBufferSize(p)
1612 #define ID3DXBuffer_Release(p) (p)->lpVtbl->Release(p)
1614 #define ID3DXBuffer_GetBufferPointer(p) (p)->GetBufferPointer()
1615 #define ID3DXBuffer_GetBufferSize(p) (p)->GetBufferSize()
1616 #define ID3DXBuffer_Release(p) (p)->Release()
1619 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1621 DWORD shaderflags = 0;
1623 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1624 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1625 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1626 if (vertstring && vertstring[0])
1630 FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1631 vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1634 vsresult = qD3DXCompileShader(vertstring, (unsigned int)strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1637 vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1638 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1639 memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1640 ID3DXBuffer_Release(vsbuffer);
1644 strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1645 Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1646 ID3DXBuffer_Release(vslog);
1649 if (fragstring && fragstring[0])
1653 FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1654 psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1657 psresult = qD3DXCompileShader(fragstring, (unsigned int)strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1660 psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1661 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1662 memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1663 ID3DXBuffer_Release(psbuffer);
1667 strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1668 Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1669 ID3DXBuffer_Release(pslog);
1672 Sys_UnloadLibrary(&d3dx9_dll);
1675 Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1679 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1680 if (FAILED(vsresult))
1681 Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1682 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1683 if (FAILED(psresult))
1684 Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1686 // free the shader data
1687 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1688 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1691 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1694 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1695 int vertstring_length = 0;
1696 int geomstring_length = 0;
1697 int fragstring_length = 0;
1700 char *vertstring, *geomstring, *fragstring;
1701 char permutationname[256];
1702 char cachename[256];
1703 int vertstrings_count = 0;
1704 int geomstrings_count = 0;
1705 int fragstrings_count = 0;
1706 const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1707 const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1708 const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1713 p->vertexshader = NULL;
1714 p->pixelshader = NULL;
1716 permutationname[0] = 0;
1718 sourcestring = R_GetShaderText(modeinfo->filename, true, false);
1720 strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1721 strlcat(cachename, "hlsl/", sizeof(cachename));
1723 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1724 vertstrings_count = 0;
1725 geomstrings_count = 0;
1726 fragstrings_count = 0;
1727 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1728 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1729 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1731 // the first pretext is which type of shader to compile as
1732 // (later these will all be bound together as a program object)
1733 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1734 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1735 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1737 // the second pretext is the mode (for example a light source)
1738 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1739 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1740 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1741 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1742 strlcat(cachename, modeinfo->name, sizeof(cachename));
1744 // now add all the permutation pretexts
1745 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1747 if (permutation & (1<<i))
1749 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1750 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1751 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1752 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1753 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1757 // keep line numbers correct
1758 vertstrings_list[vertstrings_count++] = "\n";
1759 geomstrings_list[geomstrings_count++] = "\n";
1760 fragstrings_list[fragstrings_count++] = "\n";
1765 R_CompileShader_AddStaticParms(mode, permutation);
1766 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1767 vertstrings_count += shaderstaticparms_count;
1768 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1769 geomstrings_count += shaderstaticparms_count;
1770 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1771 fragstrings_count += shaderstaticparms_count;
1773 // replace spaces in the cachename with _ characters
1774 for (i = 0;cachename[i];i++)
1775 if (cachename[i] == ' ')
1778 // now append the shader text itself
1779 vertstrings_list[vertstrings_count++] = sourcestring;
1780 geomstrings_list[geomstrings_count++] = sourcestring;
1781 fragstrings_list[fragstrings_count++] = sourcestring;
1783 vertstring_length = 0;
1784 for (i = 0;i < vertstrings_count;i++)
1785 vertstring_length += (int)strlen(vertstrings_list[i]);
1786 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1787 for (i = 0;i < vertstrings_count;t += (int)strlen(vertstrings_list[i]), i++)
1788 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1790 geomstring_length = 0;
1791 for (i = 0;i < geomstrings_count;i++)
1792 geomstring_length += (int)strlen(geomstrings_list[i]);
1793 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1794 for (i = 0;i < geomstrings_count;t += (int)strlen(geomstrings_list[i]), i++)
1795 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1797 fragstring_length = 0;
1798 for (i = 0;i < fragstrings_count;i++)
1799 fragstring_length += (int)strlen(fragstrings_list[i]);
1800 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1801 for (i = 0;i < fragstrings_count;t += (int)strlen(fragstrings_list[i]), i++)
1802 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1804 // try to load the cached shader, or generate one
1805 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1807 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1808 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1810 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1814 Mem_Free(vertstring);
1816 Mem_Free(geomstring);
1818 Mem_Free(fragstring);
1820 Mem_Free(sourcestring);
1823 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1824 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1825 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);}
1826 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);}
1827 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);}
1828 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);}
1830 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1831 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1832 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);}
1833 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);}
1834 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);}
1835 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);}
1837 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1839 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1840 if (r_hlsl_permutation != perm)
1842 r_hlsl_permutation = perm;
1843 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1845 if (!r_hlsl_permutation->compiled)
1846 R_HLSL_CompilePermutation(perm, mode, permutation);
1847 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1849 // remove features until we find a valid permutation
1851 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1853 // reduce i more quickly whenever it would not remove any bits
1854 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1855 if (!(permutation & j))
1858 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1859 if (!r_hlsl_permutation->compiled)
1860 R_HLSL_CompilePermutation(perm, mode, permutation);
1861 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1864 if (i >= SHADERPERMUTATION_COUNT)
1866 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1867 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1868 return; // no bit left to clear, entire mode is broken
1872 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1873 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1875 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1876 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1877 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1881 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1883 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1884 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1885 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1886 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1889 void R_GLSL_Restart_f(void)
1891 unsigned int i, limit;
1892 if (glslshaderstring)
1893 Mem_Free(glslshaderstring);
1894 glslshaderstring = NULL;
1895 if (hlslshaderstring)
1896 Mem_Free(hlslshaderstring);
1897 hlslshaderstring = NULL;
1898 switch(vid.renderpath)
1900 case RENDERPATH_D3D9:
1903 r_hlsl_permutation_t *p;
1904 r_hlsl_permutation = NULL;
1905 limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1906 for (i = 0;i < limit;i++)
1908 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1910 if (p->vertexshader)
1911 IDirect3DVertexShader9_Release(p->vertexshader);
1913 IDirect3DPixelShader9_Release(p->pixelshader);
1914 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1917 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1921 case RENDERPATH_D3D10:
1922 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1924 case RENDERPATH_D3D11:
1925 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1927 case RENDERPATH_GL20:
1928 case RENDERPATH_GLES2:
1930 r_glsl_permutation_t *p;
1931 r_glsl_permutation = NULL;
1932 limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1933 for (i = 0;i < limit;i++)
1935 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1937 GL_Backend_FreeProgram(p->program);
1938 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1941 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1944 case RENDERPATH_GL11:
1945 case RENDERPATH_GL13:
1946 case RENDERPATH_GLES1:
1948 case RENDERPATH_SOFT:
1953 static void R_GLSL_DumpShader_f(void)
1955 int i, language, mode, dupe;
1957 shadermodeinfo_t *modeinfo;
1960 for (language = 0;language < 2;language++)
1962 modeinfo = (language == 0 ? glslshadermodeinfo : hlslshadermodeinfo);
1963 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1965 // don't dump the same file multiple times (most or all shaders come from the same file)
1966 for (dupe = mode - 1;dupe >= 0;dupe--)
1967 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1971 text = R_GetShaderText(modeinfo[mode].filename, false, true);
1974 file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
1977 FS_Print(file, "/* The engine may define the following macros:\n");
1978 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1979 for (i = 0;i < SHADERMODE_COUNT;i++)
1980 FS_Print(file, modeinfo[i].pretext);
1981 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1982 FS_Print(file, shaderpermutationinfo[i].pretext);
1983 FS_Print(file, "*/\n");
1984 FS_Print(file, text);
1986 Con_Printf("%s written\n", modeinfo[mode].filename);
1989 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
1995 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1997 unsigned int permutation = 0;
1998 if (r_trippy.integer && !notrippy)
1999 permutation |= SHADERPERMUTATION_TRIPPY;
2000 permutation |= SHADERPERMUTATION_VIEWTINT;
2002 permutation |= SHADERPERMUTATION_DIFFUSE;
2004 permutation |= SHADERPERMUTATION_SPECULAR;
2005 if (texturemode == GL_MODULATE)
2006 permutation |= SHADERPERMUTATION_COLORMAPPING;
2007 else if (texturemode == GL_ADD)
2008 permutation |= SHADERPERMUTATION_GLOW;
2009 else if (texturemode == GL_DECAL)
2010 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2011 if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
2012 permutation |= SHADERPERMUTATION_GAMMARAMPS;
2013 if (suppresstexalpha)
2014 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2016 texturemode = GL_MODULATE;
2017 if (vid.allowalphatocoverage)
2018 GL_AlphaToCoverage(false);
2019 switch (vid.renderpath)
2021 case RENDERPATH_D3D9:
2023 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
2024 R_Mesh_TexBind(GL20TU_FIRST , first );
2025 R_Mesh_TexBind(GL20TU_SECOND, second);
2026 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
2027 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2030 case RENDERPATH_D3D10:
2031 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2033 case RENDERPATH_D3D11:
2034 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2036 case RENDERPATH_GL20:
2037 case RENDERPATH_GLES2:
2038 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2039 if (r_glsl_permutation->tex_Texture_First >= 0)
2040 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2041 if (r_glsl_permutation->tex_Texture_Second >= 0)
2042 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2043 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2044 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2046 case RENDERPATH_GL13:
2047 case RENDERPATH_GLES1:
2048 R_Mesh_TexBind(0, first );
2049 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2050 R_Mesh_TexMatrix(0, NULL);
2051 R_Mesh_TexBind(1, second);
2054 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2055 R_Mesh_TexMatrix(1, NULL);
2058 case RENDERPATH_GL11:
2059 R_Mesh_TexBind(0, first );
2060 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2061 R_Mesh_TexMatrix(0, NULL);
2063 case RENDERPATH_SOFT:
2064 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2065 R_Mesh_TexBind(GL20TU_FIRST , first );
2066 R_Mesh_TexBind(GL20TU_SECOND, second);
2071 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2073 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2076 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2078 unsigned int permutation = 0;
2079 if (r_trippy.integer && !notrippy)
2080 permutation |= SHADERPERMUTATION_TRIPPY;
2082 permutation |= SHADERPERMUTATION_DEPTHRGB;
2084 permutation |= SHADERPERMUTATION_SKELETAL;
2086 if (vid.allowalphatocoverage)
2087 GL_AlphaToCoverage(false);
2088 switch (vid.renderpath)
2090 case RENDERPATH_D3D9:
2092 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2095 case RENDERPATH_D3D10:
2096 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2098 case RENDERPATH_D3D11:
2099 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2101 case RENDERPATH_GL20:
2102 case RENDERPATH_GLES2:
2103 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2104 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2105 if (r_glsl_permutation->ubiloc_Skeletal_Transform12_UniformBlock >= 0 && rsurface.batchskeletaltransform3x4buffer) qglBindBufferRange(GL_UNIFORM_BUFFER, r_glsl_permutation->ubibind_Skeletal_Transform12_UniformBlock, rsurface.batchskeletaltransform3x4buffer->bufferobject, rsurface.batchskeletaltransform3x4offset, rsurface.batchskeletaltransform3x4size);
2108 case RENDERPATH_GL13:
2109 case RENDERPATH_GLES1:
2110 R_Mesh_TexBind(0, 0);
2111 R_Mesh_TexBind(1, 0);
2113 case RENDERPATH_GL11:
2114 R_Mesh_TexBind(0, 0);
2116 case RENDERPATH_SOFT:
2117 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2122 extern qboolean r_shadow_usingdeferredprepass;
2123 extern rtexture_t *r_shadow_attenuationgradienttexture;
2124 extern rtexture_t *r_shadow_attenuation2dtexture;
2125 extern rtexture_t *r_shadow_attenuation3dtexture;
2126 extern qboolean r_shadow_usingshadowmap2d;
2127 extern qboolean r_shadow_usingshadowmaportho;
2128 extern float r_shadow_shadowmap_texturescale[2];
2129 extern float r_shadow_shadowmap_parameters[4];
2130 extern qboolean r_shadow_shadowmapvsdct;
2131 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2132 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2133 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2134 extern matrix4x4_t r_shadow_shadowmapmatrix;
2135 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2136 extern int r_shadow_prepass_width;
2137 extern int r_shadow_prepass_height;
2138 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2139 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2140 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2141 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2143 #define BLENDFUNC_ALLOWS_COLORMOD 1
2144 #define BLENDFUNC_ALLOWS_FOG 2
2145 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2146 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2147 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2148 static int R_BlendFuncFlags(int src, int dst)
2152 // a blendfunc allows colormod if:
2153 // a) it can never keep the destination pixel invariant, or
2154 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2155 // this is to prevent unintended side effects from colormod
2157 // a blendfunc allows fog if:
2158 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2159 // this is to prevent unintended side effects from fog
2161 // these checks are the output of fogeval.pl
2163 r |= BLENDFUNC_ALLOWS_COLORMOD;
2164 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2165 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2166 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2167 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2168 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2169 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2170 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2171 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2172 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2173 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2174 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2175 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2176 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2177 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2178 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2179 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2180 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2181 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2182 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2183 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2184 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2189 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)
2191 // select a permutation of the lighting shader appropriate to this
2192 // combination of texture, entity, light source, and fogging, only use the
2193 // minimum features necessary to avoid wasting rendering time in the
2194 // fragment shader on features that are not being used
2195 unsigned int permutation = 0;
2196 unsigned int mode = 0;
2198 static float dummy_colormod[3] = {1, 1, 1};
2199 float *colormod = rsurface.colormod;
2201 matrix4x4_t tempmatrix;
2202 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2203 if (r_trippy.integer && !notrippy)
2204 permutation |= SHADERPERMUTATION_TRIPPY;
2205 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2206 permutation |= SHADERPERMUTATION_ALPHAKILL;
2207 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_OCCLUDE)
2208 permutation |= SHADERPERMUTATION_OCCLUDE;
2209 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2210 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2211 if (rsurfacepass == RSURFPASS_BACKGROUND)
2213 // distorted background
2214 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2216 mode = SHADERMODE_WATER;
2217 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2218 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2219 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2221 // this is the right thing to do for wateralpha
2222 GL_BlendFunc(GL_ONE, GL_ZERO);
2223 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2227 // this is the right thing to do for entity alpha
2228 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2229 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2232 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2234 mode = SHADERMODE_REFRACTION;
2235 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2236 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2237 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2238 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2242 mode = SHADERMODE_GENERIC;
2243 permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2244 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2245 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2247 if (vid.allowalphatocoverage)
2248 GL_AlphaToCoverage(false);
2250 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2252 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2254 switch(rsurface.texture->offsetmapping)
2256 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2257 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2258 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2259 case OFFSETMAPPING_OFF: break;
2262 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2263 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2264 // normalmap (deferred prepass), may use alpha test on diffuse
2265 mode = SHADERMODE_DEFERREDGEOMETRY;
2266 GL_BlendFunc(GL_ONE, GL_ZERO);
2267 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2268 if (vid.allowalphatocoverage)
2269 GL_AlphaToCoverage(false);
2271 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2273 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2275 switch(rsurface.texture->offsetmapping)
2277 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2278 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2279 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2280 case OFFSETMAPPING_OFF: break;
2283 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2284 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2285 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2286 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2288 mode = SHADERMODE_LIGHTSOURCE;
2289 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2290 permutation |= SHADERPERMUTATION_CUBEFILTER;
2291 if (diffusescale > 0)
2292 permutation |= SHADERPERMUTATION_DIFFUSE;
2293 if (specularscale > 0)
2294 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2295 if (r_refdef.fogenabled)
2296 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2297 if (rsurface.texture->colormapping)
2298 permutation |= SHADERPERMUTATION_COLORMAPPING;
2299 if (r_shadow_usingshadowmap2d)
2301 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2302 if(r_shadow_shadowmapvsdct)
2303 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2305 if (r_shadow_shadowmap2ddepthbuffer)
2306 permutation |= SHADERPERMUTATION_DEPTHRGB;
2308 if (rsurface.texture->reflectmasktexture)
2309 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2310 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2311 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2312 if (vid.allowalphatocoverage)
2313 GL_AlphaToCoverage(false);
2315 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2317 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2319 switch(rsurface.texture->offsetmapping)
2321 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2322 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2323 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2324 case OFFSETMAPPING_OFF: break;
2327 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2328 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2329 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2330 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2331 // unshaded geometry (fullbright or ambient model lighting)
2332 mode = SHADERMODE_FLATCOLOR;
2333 ambientscale = diffusescale = specularscale = 0;
2334 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2335 permutation |= SHADERPERMUTATION_GLOW;
2336 if (r_refdef.fogenabled)
2337 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2338 if (rsurface.texture->colormapping)
2339 permutation |= SHADERPERMUTATION_COLORMAPPING;
2340 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2342 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2343 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2345 if (r_shadow_shadowmap2ddepthbuffer)
2346 permutation |= SHADERPERMUTATION_DEPTHRGB;
2348 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2349 permutation |= SHADERPERMUTATION_REFLECTION;
2350 if (rsurface.texture->reflectmasktexture)
2351 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2352 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2353 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2354 // when using alphatocoverage, we don't need alphakill
2355 if (vid.allowalphatocoverage)
2357 if (r_transparent_alphatocoverage.integer)
2359 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2360 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2363 GL_AlphaToCoverage(false);
2366 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2368 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2370 switch(rsurface.texture->offsetmapping)
2372 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2373 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2374 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2375 case OFFSETMAPPING_OFF: break;
2378 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2379 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2380 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2381 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2382 // directional model lighting
2383 mode = SHADERMODE_LIGHTDIRECTION;
2384 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2385 permutation |= SHADERPERMUTATION_GLOW;
2386 permutation |= SHADERPERMUTATION_DIFFUSE;
2387 if (specularscale > 0)
2388 permutation |= SHADERPERMUTATION_SPECULAR;
2389 if (r_refdef.fogenabled)
2390 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2391 if (rsurface.texture->colormapping)
2392 permutation |= SHADERPERMUTATION_COLORMAPPING;
2393 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2395 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2396 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2398 if (r_shadow_shadowmap2ddepthbuffer)
2399 permutation |= SHADERPERMUTATION_DEPTHRGB;
2401 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2402 permutation |= SHADERPERMUTATION_REFLECTION;
2403 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2404 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2405 if (rsurface.texture->reflectmasktexture)
2406 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2407 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2409 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2410 if (r_shadow_bouncegriddirectional)
2411 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2413 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2414 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2415 // when using alphatocoverage, we don't need alphakill
2416 if (vid.allowalphatocoverage)
2418 if (r_transparent_alphatocoverage.integer)
2420 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2421 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2424 GL_AlphaToCoverage(false);
2427 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2429 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2431 switch(rsurface.texture->offsetmapping)
2433 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2434 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2435 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2436 case OFFSETMAPPING_OFF: break;
2439 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2440 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2441 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2442 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2443 // ambient model lighting
2444 mode = SHADERMODE_LIGHTDIRECTION;
2445 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2446 permutation |= SHADERPERMUTATION_GLOW;
2447 if (r_refdef.fogenabled)
2448 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2449 if (rsurface.texture->colormapping)
2450 permutation |= SHADERPERMUTATION_COLORMAPPING;
2451 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2453 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2454 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2456 if (r_shadow_shadowmap2ddepthbuffer)
2457 permutation |= SHADERPERMUTATION_DEPTHRGB;
2459 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2460 permutation |= SHADERPERMUTATION_REFLECTION;
2461 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2462 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2463 if (rsurface.texture->reflectmasktexture)
2464 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2465 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2467 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2468 if (r_shadow_bouncegriddirectional)
2469 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2471 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2472 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2473 // when using alphatocoverage, we don't need alphakill
2474 if (vid.allowalphatocoverage)
2476 if (r_transparent_alphatocoverage.integer)
2478 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2479 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2482 GL_AlphaToCoverage(false);
2487 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2489 switch(rsurface.texture->offsetmapping)
2491 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2492 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2493 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2494 case OFFSETMAPPING_OFF: break;
2497 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2498 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2499 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2500 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2502 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2503 permutation |= SHADERPERMUTATION_GLOW;
2504 if (r_refdef.fogenabled)
2505 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2506 if (rsurface.texture->colormapping)
2507 permutation |= SHADERPERMUTATION_COLORMAPPING;
2508 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2510 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2511 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2513 if (r_shadow_shadowmap2ddepthbuffer)
2514 permutation |= SHADERPERMUTATION_DEPTHRGB;
2516 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2517 permutation |= SHADERPERMUTATION_REFLECTION;
2518 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2519 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2520 if (rsurface.texture->reflectmasktexture)
2521 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2522 if (FAKELIGHT_ENABLED)
2524 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2525 mode = SHADERMODE_FAKELIGHT;
2526 permutation |= SHADERPERMUTATION_DIFFUSE;
2527 if (specularscale > 0)
2528 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2530 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2532 // deluxemapping (light direction texture)
2533 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2534 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2536 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2537 permutation |= SHADERPERMUTATION_DIFFUSE;
2538 if (specularscale > 0)
2539 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2541 else if (r_glsl_deluxemapping.integer >= 2)
2543 // fake deluxemapping (uniform light direction in tangentspace)
2544 if (rsurface.uselightmaptexture)
2545 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2547 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2548 permutation |= SHADERPERMUTATION_DIFFUSE;
2549 if (specularscale > 0)
2550 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2552 else if (rsurface.uselightmaptexture)
2554 // ordinary lightmapping (q1bsp, q3bsp)
2555 mode = SHADERMODE_LIGHTMAP;
2559 // ordinary vertex coloring (q3bsp)
2560 mode = SHADERMODE_VERTEXCOLOR;
2562 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2564 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2565 if (r_shadow_bouncegriddirectional)
2566 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2568 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2569 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2570 // when using alphatocoverage, we don't need alphakill
2571 if (vid.allowalphatocoverage)
2573 if (r_transparent_alphatocoverage.integer)
2575 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2576 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2579 GL_AlphaToCoverage(false);
2582 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2583 colormod = dummy_colormod;
2584 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2585 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2586 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2587 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2588 switch(vid.renderpath)
2590 case RENDERPATH_D3D9:
2592 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);
2593 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2594 R_SetupShader_SetPermutationHLSL(mode, permutation);
2595 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2596 if (mode == SHADERMODE_LIGHTSOURCE)
2598 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2599 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2603 if (mode == SHADERMODE_LIGHTDIRECTION)
2605 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2608 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2609 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2610 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2611 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2612 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2614 if (mode == SHADERMODE_LIGHTSOURCE)
2616 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2617 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2618 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2619 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2620 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2622 // additive passes are only darkened by fog, not tinted
2623 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2624 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2628 if (mode == SHADERMODE_FLATCOLOR)
2630 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2632 else if (mode == SHADERMODE_LIGHTDIRECTION)
2634 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]);
2635 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2636 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);
2637 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2638 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2639 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2640 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2644 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2645 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2646 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);
2647 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2648 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2650 // additive passes are only darkened by fog, not tinted
2651 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2652 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2654 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2655 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);
2656 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2657 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2658 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2659 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2660 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2661 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2662 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2663 if (mode == SHADERMODE_WATER)
2664 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2666 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2667 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2668 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2669 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));
2670 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2671 if (rsurface.texture->pantstexture)
2672 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2674 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2675 if (rsurface.texture->shirttexture)
2676 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2678 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2679 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2680 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2681 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2682 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2683 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2684 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2685 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2686 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2687 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2689 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2690 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2691 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2692 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2694 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2695 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2696 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2697 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2698 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2699 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2700 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2701 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2702 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2703 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2704 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2705 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2706 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2707 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2708 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2709 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2710 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2711 if (rsurfacepass == RSURFPASS_BACKGROUND)
2713 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2714 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2715 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2719 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2721 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2722 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2723 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2724 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2726 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2727 if (rsurface.rtlight)
2729 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2730 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2735 case RENDERPATH_D3D10:
2736 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2738 case RENDERPATH_D3D11:
2739 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2741 case RENDERPATH_GL20:
2742 case RENDERPATH_GLES2:
2743 if (!vid.useinterleavedarrays)
2745 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);
2746 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2747 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2748 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2749 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2750 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2751 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2752 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2753 R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2754 R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2755 R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2759 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);
2760 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2762 // this has to be after RSurf_PrepareVerticesForBatch
2763 if (rsurface.batchskeletaltransform3x4buffer)
2764 permutation |= SHADERPERMUTATION_SKELETAL;
2765 R_SetupShader_SetPermutationGLSL(mode, permutation);
2766 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2767 if (r_glsl_permutation->ubiloc_Skeletal_Transform12_UniformBlock >= 0 && rsurface.batchskeletaltransform3x4buffer) qglBindBufferRange(GL_UNIFORM_BUFFER, r_glsl_permutation->ubibind_Skeletal_Transform12_UniformBlock, rsurface.batchskeletaltransform3x4buffer->bufferobject, rsurface.batchskeletaltransform3x4offset, rsurface.batchskeletaltransform3x4size);
2769 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2770 if (mode == SHADERMODE_LIGHTSOURCE)
2772 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2773 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2774 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2775 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2776 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2777 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);
2779 // additive passes are only darkened by fog, not tinted
2780 if (r_glsl_permutation->loc_FogColor >= 0)
2781 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2782 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);
2786 if (mode == SHADERMODE_FLATCOLOR)
2788 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2790 else if (mode == SHADERMODE_LIGHTDIRECTION)
2792 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]);
2793 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]);
2794 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);
2795 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2796 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2797 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]);
2798 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]);
2802 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]);
2803 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]);
2804 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);
2805 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2806 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2808 // additive passes are only darkened by fog, not tinted
2809 if (r_glsl_permutation->loc_FogColor >= 0)
2811 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2812 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2814 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2816 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);
2817 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]);
2818 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]);
2819 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]);
2820 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]);
2821 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2822 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2823 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);
2824 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]);
2826 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2827 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2828 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2829 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]);
2830 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]);
2832 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2833 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));
2834 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2835 if (r_glsl_permutation->loc_Color_Pants >= 0)
2837 if (rsurface.texture->pantstexture)
2838 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2840 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2842 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2844 if (rsurface.texture->shirttexture)
2845 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2847 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2849 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]);
2850 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2851 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2852 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2853 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2854 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2855 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2856 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2857 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2859 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);
2860 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2861 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]);
2862 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2863 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);}
2864 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2866 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2867 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2868 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2869 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2870 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2871 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2872 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2873 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2874 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2875 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2876 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2877 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2878 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2879 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2880 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);
2881 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2882 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2883 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2884 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2885 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2886 if (rsurfacepass == RSURFPASS_BACKGROUND)
2888 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);
2889 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);
2890 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);
2894 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);
2896 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2897 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2898 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2899 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2901 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture );
2902 if (rsurface.rtlight)
2904 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2905 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2908 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2911 case RENDERPATH_GL11:
2912 case RENDERPATH_GL13:
2913 case RENDERPATH_GLES1:
2915 case RENDERPATH_SOFT:
2916 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);
2917 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2918 R_SetupShader_SetPermutationSoft(mode, permutation);
2919 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2920 if (mode == SHADERMODE_LIGHTSOURCE)
2922 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2923 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2924 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2925 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2926 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2927 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2929 // additive passes are only darkened by fog, not tinted
2930 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2931 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2935 if (mode == SHADERMODE_FLATCOLOR)
2937 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2939 else if (mode == SHADERMODE_LIGHTDIRECTION)
2941 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]);
2942 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2943 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);
2944 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2945 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2946 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]);
2947 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2951 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2952 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2953 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);
2954 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2955 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2957 // additive passes are only darkened by fog, not tinted
2958 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2959 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2961 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2962 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);
2963 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]);
2964 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]);
2965 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]);
2966 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]);
2967 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2968 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2969 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2970 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2972 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2973 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2974 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2975 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2976 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]);
2978 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2979 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));
2980 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2981 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2983 if (rsurface.texture->pantstexture)
2984 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2986 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2988 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2990 if (rsurface.texture->shirttexture)
2991 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2993 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2995 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2996 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2997 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2998 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2999 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
3000 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
3001 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3002 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3003 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
3005 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
3006 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
3007 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3008 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3010 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
3011 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
3012 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
3013 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
3014 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
3015 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
3016 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
3017 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
3018 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
3019 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
3020 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
3021 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
3022 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
3023 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
3024 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
3025 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
3026 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3027 if (rsurfacepass == RSURFPASS_BACKGROUND)
3029 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
3030 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
3031 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3035 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3037 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3038 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
3039 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
3040 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
3042 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
3043 if (rsurface.rtlight)
3045 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3046 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3053 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3055 // select a permutation of the lighting shader appropriate to this
3056 // combination of texture, entity, light source, and fogging, only use the
3057 // minimum features necessary to avoid wasting rendering time in the
3058 // fragment shader on features that are not being used
3059 unsigned int permutation = 0;
3060 unsigned int mode = 0;
3061 const float *lightcolorbase = rtlight->currentcolor;
3062 float ambientscale = rtlight->ambientscale;
3063 float diffusescale = rtlight->diffusescale;
3064 float specularscale = rtlight->specularscale;
3065 // this is the location of the light in view space
3066 vec3_t viewlightorigin;
3067 // this transforms from view space (camera) to light space (cubemap)
3068 matrix4x4_t viewtolight;
3069 matrix4x4_t lighttoview;
3070 float viewtolight16f[16];
3072 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3073 if (rtlight->currentcubemap != r_texture_whitecube)
3074 permutation |= SHADERPERMUTATION_CUBEFILTER;
3075 if (diffusescale > 0)
3076 permutation |= SHADERPERMUTATION_DIFFUSE;
3077 if (specularscale > 0 && r_shadow_gloss.integer > 0)
3078 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3079 if (r_shadow_usingshadowmap2d)
3081 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3082 if (r_shadow_shadowmapvsdct)
3083 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3085 if (r_shadow_shadowmap2ddepthbuffer)
3086 permutation |= SHADERPERMUTATION_DEPTHRGB;
3088 if (vid.allowalphatocoverage)
3089 GL_AlphaToCoverage(false);
3090 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3091 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3092 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3093 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3094 switch(vid.renderpath)
3096 case RENDERPATH_D3D9:
3098 R_SetupShader_SetPermutationHLSL(mode, permutation);
3099 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3100 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3101 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3102 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3103 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3104 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3105 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3106 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);
3107 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3108 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/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 );
3117 case RENDERPATH_D3D10:
3118 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3120 case RENDERPATH_D3D11:
3121 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3123 case RENDERPATH_GL20:
3124 case RENDERPATH_GLES2:
3125 R_SetupShader_SetPermutationGLSL(mode, permutation);
3126 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3127 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
3128 if (r_glsl_permutation->loc_DeferredColor_Ambient >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3129 if (r_glsl_permutation->loc_DeferredColor_Diffuse >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3130 if (r_glsl_permutation->loc_DeferredColor_Specular >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3131 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]);
3132 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]);
3133 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);
3134 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]);
3135 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
3137 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
3138 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
3139 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
3140 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2ddepthtexture );
3141 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
3143 case RENDERPATH_GL11:
3144 case RENDERPATH_GL13:
3145 case RENDERPATH_GLES1:
3147 case RENDERPATH_SOFT:
3148 R_SetupShader_SetPermutationGLSL(mode, permutation);
3149 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3150 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
3151 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3152 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3153 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3154 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3155 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]);
3156 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);
3157 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3158 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3160 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3161 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3162 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3163 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2ddepthtexture );
3164 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3169 #define SKINFRAME_HASH 1024
3173 unsigned int loadsequence; // incremented each level change
3174 memexpandablearray_t array;
3175 skinframe_t *hash[SKINFRAME_HASH];
3178 r_skinframe_t r_skinframe;
3180 void R_SkinFrame_PrepareForPurge(void)
3182 r_skinframe.loadsequence++;
3183 // wrap it without hitting zero
3184 if (r_skinframe.loadsequence >= 200)
3185 r_skinframe.loadsequence = 1;
3188 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3192 // mark the skinframe as used for the purging code
3193 skinframe->loadsequence = r_skinframe.loadsequence;
3196 void R_SkinFrame_Purge(void)
3200 for (i = 0;i < SKINFRAME_HASH;i++)
3202 for (s = r_skinframe.hash[i];s;s = s->next)
3204 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3206 if (s->merged == s->base)
3208 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3209 R_PurgeTexture(s->stain );s->stain = NULL;
3210 R_PurgeTexture(s->merged);s->merged = NULL;
3211 R_PurgeTexture(s->base );s->base = NULL;
3212 R_PurgeTexture(s->pants );s->pants = NULL;
3213 R_PurgeTexture(s->shirt );s->shirt = NULL;
3214 R_PurgeTexture(s->nmap );s->nmap = NULL;
3215 R_PurgeTexture(s->gloss );s->gloss = NULL;
3216 R_PurgeTexture(s->glow );s->glow = NULL;
3217 R_PurgeTexture(s->fog );s->fog = NULL;
3218 R_PurgeTexture(s->reflect);s->reflect = NULL;
3219 s->loadsequence = 0;
3225 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3227 char basename[MAX_QPATH];
3229 Image_StripImageExtension(name, basename, sizeof(basename));
3231 if( last == NULL ) {
3233 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3234 item = r_skinframe.hash[hashindex];
3239 // linearly search through the hash bucket
3240 for( ; item ; item = item->next ) {
3241 if( !strcmp( item->basename, basename ) ) {
3248 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3252 char basename[MAX_QPATH];
3254 Image_StripImageExtension(name, basename, sizeof(basename));
3256 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3257 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3258 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3262 rtexture_t *dyntexture;
3263 // check whether its a dynamic texture
3264 dyntexture = CL_GetDynTexture( basename );
3265 if (!add && !dyntexture)
3267 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3268 memset(item, 0, sizeof(*item));
3269 strlcpy(item->basename, basename, sizeof(item->basename));
3270 item->base = dyntexture; // either NULL or dyntexture handle
3271 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3272 item->comparewidth = comparewidth;
3273 item->compareheight = compareheight;
3274 item->comparecrc = comparecrc;
3275 item->next = r_skinframe.hash[hashindex];
3276 r_skinframe.hash[hashindex] = item;
3278 else if (textureflags & TEXF_FORCE_RELOAD)
3280 rtexture_t *dyntexture;
3281 // check whether its a dynamic texture
3282 dyntexture = CL_GetDynTexture( basename );
3283 if (!add && !dyntexture)
3285 if (item->merged == item->base)
3286 item->merged = NULL;
3287 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3288 R_PurgeTexture(item->stain );item->stain = NULL;
3289 R_PurgeTexture(item->merged);item->merged = NULL;
3290 R_PurgeTexture(item->base );item->base = NULL;
3291 R_PurgeTexture(item->pants );item->pants = NULL;
3292 R_PurgeTexture(item->shirt );item->shirt = NULL;
3293 R_PurgeTexture(item->nmap );item->nmap = NULL;
3294 R_PurgeTexture(item->gloss );item->gloss = NULL;
3295 R_PurgeTexture(item->glow );item->glow = NULL;
3296 R_PurgeTexture(item->fog );item->fog = NULL;
3297 R_PurgeTexture(item->reflect);item->reflect = NULL;
3298 item->loadsequence = 0;
3300 else if( item->base == NULL )
3302 rtexture_t *dyntexture;
3303 // check whether its a dynamic texture
3304 // 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]
3305 dyntexture = CL_GetDynTexture( basename );
3306 item->base = dyntexture; // either NULL or dyntexture handle
3309 R_SkinFrame_MarkUsed(item);
3313 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3315 unsigned long long avgcolor[5], wsum; \
3323 for(pix = 0; pix < cnt; ++pix) \
3326 for(comp = 0; comp < 3; ++comp) \
3328 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3331 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3333 for(comp = 0; comp < 3; ++comp) \
3334 avgcolor[comp] += getpixel * w; \
3337 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3338 avgcolor[4] += getpixel; \
3340 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3342 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3343 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3344 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3345 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3348 extern cvar_t gl_picmip;
3349 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3352 unsigned char *pixels;
3353 unsigned char *bumppixels;
3354 unsigned char *basepixels = NULL;
3355 int basepixels_width = 0;
3356 int basepixels_height = 0;
3357 skinframe_t *skinframe;
3358 rtexture_t *ddsbase = NULL;
3359 qboolean ddshasalpha = false;
3360 float ddsavgcolor[4];
3361 char basename[MAX_QPATH];
3362 int miplevel = R_PicmipForFlags(textureflags);
3363 int savemiplevel = miplevel;
3367 if (cls.state == ca_dedicated)
3370 // return an existing skinframe if already loaded
3371 // if loading of the first image fails, don't make a new skinframe as it
3372 // would cause all future lookups of this to be missing
3373 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3374 if (skinframe && skinframe->base)
3377 Image_StripImageExtension(name, basename, sizeof(basename));
3379 // check for DDS texture file first
3380 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3382 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3383 if (basepixels == NULL)
3387 // FIXME handle miplevel
3389 if (developer_loading.integer)
3390 Con_Printf("loading skin \"%s\"\n", name);
3392 // we've got some pixels to store, so really allocate this new texture now
3394 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3395 textureflags &= ~TEXF_FORCE_RELOAD;
3396 skinframe->stain = NULL;
3397 skinframe->merged = NULL;
3398 skinframe->base = NULL;
3399 skinframe->pants = NULL;
3400 skinframe->shirt = NULL;
3401 skinframe->nmap = NULL;
3402 skinframe->gloss = NULL;
3403 skinframe->glow = NULL;
3404 skinframe->fog = NULL;
3405 skinframe->reflect = NULL;
3406 skinframe->hasalpha = false;
3407 // we could store the q2animname here too
3411 skinframe->base = ddsbase;
3412 skinframe->hasalpha = ddshasalpha;
3413 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3414 if (r_loadfog && skinframe->hasalpha)
3415 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);
3416 //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]);
3420 basepixels_width = image_width;
3421 basepixels_height = image_height;
3422 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);
3423 if (textureflags & TEXF_ALPHA)
3425 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3427 if (basepixels[j] < 255)
3429 skinframe->hasalpha = true;
3433 if (r_loadfog && skinframe->hasalpha)
3435 // has transparent pixels
3436 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3437 for (j = 0;j < image_width * image_height * 4;j += 4)
3442 pixels[j+3] = basepixels[j+3];
3444 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);
3448 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3450 //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]);
3451 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3452 R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3453 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3454 R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3460 mymiplevel = savemiplevel;
3461 if (r_loadnormalmap)
3462 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);
3463 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3465 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3466 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3467 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3468 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3471 // _norm is the name used by tenebrae and has been adopted as standard
3472 if (r_loadnormalmap && skinframe->nmap == NULL)
3474 mymiplevel = savemiplevel;
3475 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3477 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);
3481 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3483 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3484 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3485 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);
3487 Mem_Free(bumppixels);
3489 else if (r_shadow_bumpscale_basetexture.value > 0)
3491 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3492 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3493 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);
3497 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3498 R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3502 // _luma is supported only for tenebrae compatibility
3503 // _glow is the preferred name
3504 mymiplevel = savemiplevel;
3505 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))))
3507 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);
3509 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3510 R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3512 Mem_Free(pixels);pixels = NULL;
3515 mymiplevel = savemiplevel;
3516 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3518 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);
3520 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3521 R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3527 mymiplevel = savemiplevel;
3528 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3530 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);
3532 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3533 R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3539 mymiplevel = savemiplevel;
3540 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3542 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);
3544 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3545 R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3551 mymiplevel = savemiplevel;
3552 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3554 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);
3556 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3557 R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3564 Mem_Free(basepixels);
3569 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3570 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3573 unsigned char *temp1, *temp2;
3574 skinframe_t *skinframe;
3577 if (cls.state == ca_dedicated)
3580 // if already loaded just return it, otherwise make a new skinframe
3581 skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3582 if (skinframe->base)
3584 textureflags &= ~TEXF_FORCE_RELOAD;
3586 skinframe->stain = NULL;
3587 skinframe->merged = NULL;
3588 skinframe->base = NULL;
3589 skinframe->pants = NULL;
3590 skinframe->shirt = NULL;
3591 skinframe->nmap = NULL;
3592 skinframe->gloss = NULL;
3593 skinframe->glow = NULL;
3594 skinframe->fog = NULL;
3595 skinframe->reflect = NULL;
3596 skinframe->hasalpha = false;
3598 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3602 if (developer_loading.integer)
3603 Con_Printf("loading 32bit skin \"%s\"\n", name);
3605 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3607 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3608 temp2 = temp1 + width * height * 4;
3609 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3610 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);
3613 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3614 if (textureflags & TEXF_ALPHA)
3616 for (i = 3;i < width * height * 4;i += 4)
3618 if (skindata[i] < 255)
3620 skinframe->hasalpha = true;
3624 if (r_loadfog && skinframe->hasalpha)
3626 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3627 memcpy(fogpixels, skindata, width * height * 4);
3628 for (i = 0;i < width * height * 4;i += 4)
3629 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3630 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3631 Mem_Free(fogpixels);
3635 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3636 //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]);
3641 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3645 skinframe_t *skinframe;
3647 if (cls.state == ca_dedicated)
3650 // if already loaded just return it, otherwise make a new skinframe
3651 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3652 if (skinframe->base)
3654 //textureflags &= ~TEXF_FORCE_RELOAD;
3656 skinframe->stain = NULL;
3657 skinframe->merged = NULL;
3658 skinframe->base = NULL;
3659 skinframe->pants = NULL;
3660 skinframe->shirt = NULL;
3661 skinframe->nmap = NULL;
3662 skinframe->gloss = NULL;
3663 skinframe->glow = NULL;
3664 skinframe->fog = NULL;
3665 skinframe->reflect = NULL;
3666 skinframe->hasalpha = false;
3668 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3672 if (developer_loading.integer)
3673 Con_Printf("loading quake skin \"%s\"\n", name);
3675 // 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)
3676 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3677 memcpy(skinframe->qpixels, skindata, width*height);
3678 skinframe->qwidth = width;
3679 skinframe->qheight = height;
3682 for (i = 0;i < width * height;i++)
3683 featuresmask |= palette_featureflags[skindata[i]];
3685 skinframe->hasalpha = false;
3686 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3687 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3688 skinframe->qgeneratemerged = true;
3689 skinframe->qgeneratebase = skinframe->qhascolormapping;
3690 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3692 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3693 //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]);
3698 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3702 unsigned char *skindata;
3705 if (!skinframe->qpixels)
3708 if (!skinframe->qhascolormapping)
3709 colormapped = false;
3713 if (!skinframe->qgeneratebase)
3718 if (!skinframe->qgeneratemerged)
3722 width = skinframe->qwidth;
3723 height = skinframe->qheight;
3724 skindata = skinframe->qpixels;
3726 if (skinframe->qgeneratenmap)
3728 unsigned char *temp1, *temp2;
3729 skinframe->qgeneratenmap = false;
3730 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3731 temp2 = temp1 + width * height * 4;
3732 // use either a custom palette or the quake palette
3733 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3734 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3735 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);
3739 if (skinframe->qgenerateglow)
3741 skinframe->qgenerateglow = false;
3742 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
3747 skinframe->qgeneratebase = false;
3748 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);
3749 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);
3750 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);
3754 skinframe->qgeneratemerged = false;
3755 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);
3758 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3760 Mem_Free(skinframe->qpixels);
3761 skinframe->qpixels = NULL;
3765 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)
3768 skinframe_t *skinframe;
3771 if (cls.state == ca_dedicated)
3774 // if already loaded just return it, otherwise make a new skinframe
3775 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3776 if (skinframe->base)
3778 textureflags &= ~TEXF_FORCE_RELOAD;
3780 skinframe->stain = NULL;
3781 skinframe->merged = NULL;
3782 skinframe->base = NULL;
3783 skinframe->pants = NULL;
3784 skinframe->shirt = NULL;
3785 skinframe->nmap = NULL;
3786 skinframe->gloss = NULL;
3787 skinframe->glow = NULL;
3788 skinframe->fog = NULL;
3789 skinframe->reflect = NULL;
3790 skinframe->hasalpha = false;
3792 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3796 if (developer_loading.integer)
3797 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3799 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3800 if (textureflags & TEXF_ALPHA)
3802 for (i = 0;i < width * height;i++)
3804 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3806 skinframe->hasalpha = true;
3810 if (r_loadfog && skinframe->hasalpha)
3811 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3814 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3815 //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]);
3820 skinframe_t *R_SkinFrame_LoadMissing(void)
3822 skinframe_t *skinframe;
3824 if (cls.state == ca_dedicated)
3827 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3828 skinframe->stain = NULL;
3829 skinframe->merged = NULL;
3830 skinframe->base = NULL;
3831 skinframe->pants = NULL;
3832 skinframe->shirt = NULL;
3833 skinframe->nmap = NULL;
3834 skinframe->gloss = NULL;
3835 skinframe->glow = NULL;
3836 skinframe->fog = NULL;
3837 skinframe->reflect = NULL;
3838 skinframe->hasalpha = false;
3840 skinframe->avgcolor[0] = rand() / RAND_MAX;
3841 skinframe->avgcolor[1] = rand() / RAND_MAX;
3842 skinframe->avgcolor[2] = rand() / RAND_MAX;
3843 skinframe->avgcolor[3] = 1;
3848 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3849 typedef struct suffixinfo_s
3852 qboolean flipx, flipy, flipdiagonal;
3855 static suffixinfo_t suffix[3][6] =
3858 {"px", false, false, false},
3859 {"nx", false, false, false},
3860 {"py", false, false, false},
3861 {"ny", false, false, false},
3862 {"pz", false, false, false},
3863 {"nz", false, false, false}
3866 {"posx", false, false, false},
3867 {"negx", false, false, false},
3868 {"posy", false, false, false},
3869 {"negy", false, false, false},
3870 {"posz", false, false, false},
3871 {"negz", false, false, false}
3874 {"rt", true, false, true},
3875 {"lf", false, true, true},
3876 {"ft", true, true, false},
3877 {"bk", false, false, false},
3878 {"up", true, false, true},
3879 {"dn", true, false, true}
3883 static int componentorder[4] = {0, 1, 2, 3};
3885 static rtexture_t *R_LoadCubemap(const char *basename)
3887 int i, j, cubemapsize;
3888 unsigned char *cubemappixels, *image_buffer;
3889 rtexture_t *cubemaptexture;
3891 // must start 0 so the first loadimagepixels has no requested width/height
3893 cubemappixels = NULL;
3894 cubemaptexture = NULL;
3895 // keep trying different suffix groups (posx, px, rt) until one loads
3896 for (j = 0;j < 3 && !cubemappixels;j++)
3898 // load the 6 images in the suffix group
3899 for (i = 0;i < 6;i++)
3901 // generate an image name based on the base and and suffix
3902 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3904 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3906 // an image loaded, make sure width and height are equal
3907 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3909 // if this is the first image to load successfully, allocate the cubemap memory
3910 if (!cubemappixels && image_width >= 1)
3912 cubemapsize = image_width;
3913 // note this clears to black, so unavailable sides are black
3914 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3916 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3918 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);
3921 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3923 Mem_Free(image_buffer);
3927 // if a cubemap loaded, upload it
3930 if (developer_loading.integer)
3931 Con_Printf("loading cubemap \"%s\"\n", basename);
3933 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);
3934 Mem_Free(cubemappixels);
3938 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3939 if (developer_loading.integer)
3941 Con_Printf("(tried tried images ");
3942 for (j = 0;j < 3;j++)
3943 for (i = 0;i < 6;i++)
3944 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3945 Con_Print(" and was unable to find any of them).\n");
3948 return cubemaptexture;
3951 rtexture_t *R_GetCubemap(const char *basename)
3954 for (i = 0;i < r_texture_numcubemaps;i++)
3955 if (r_texture_cubemaps[i] != NULL)
3956 if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3957 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3958 if (i >= MAX_CUBEMAPS || !r_main_mempool)
3959 return r_texture_whitecube;
3960 r_texture_numcubemaps++;
3961 r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3962 strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3963 r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3964 return r_texture_cubemaps[i]->texture;
3967 static void R_Main_FreeViewCache(void)
3969 if (r_refdef.viewcache.entityvisible)
3970 Mem_Free(r_refdef.viewcache.entityvisible);
3971 if (r_refdef.viewcache.world_pvsbits)
3972 Mem_Free(r_refdef.viewcache.world_pvsbits);
3973 if (r_refdef.viewcache.world_leafvisible)
3974 Mem_Free(r_refdef.viewcache.world_leafvisible);
3975 if (r_refdef.viewcache.world_surfacevisible)
3976 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3977 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3980 static void R_Main_ResizeViewCache(void)
3982 int numentities = r_refdef.scene.numentities;
3983 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3984 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3985 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3986 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3987 if (r_refdef.viewcache.maxentities < numentities)
3989 r_refdef.viewcache.maxentities = numentities;
3990 if (r_refdef.viewcache.entityvisible)
3991 Mem_Free(r_refdef.viewcache.entityvisible);
3992 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3994 if (r_refdef.viewcache.world_numclusters != numclusters)
3996 r_refdef.viewcache.world_numclusters = numclusters;
3997 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3998 if (r_refdef.viewcache.world_pvsbits)
3999 Mem_Free(r_refdef.viewcache.world_pvsbits);
4000 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
4002 if (r_refdef.viewcache.world_numleafs != numleafs)
4004 r_refdef.viewcache.world_numleafs = numleafs;
4005 if (r_refdef.viewcache.world_leafvisible)
4006 Mem_Free(r_refdef.viewcache.world_leafvisible);
4007 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
4009 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
4011 r_refdef.viewcache.world_numsurfaces = numsurfaces;
4012 if (r_refdef.viewcache.world_surfacevisible)
4013 Mem_Free(r_refdef.viewcache.world_surfacevisible);
4014 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
4018 extern rtexture_t *loadingscreentexture;
4019 static void gl_main_start(void)
4021 loadingscreentexture = NULL;
4022 r_texture_blanknormalmap = NULL;
4023 r_texture_white = NULL;
4024 r_texture_grey128 = NULL;
4025 r_texture_black = NULL;
4026 r_texture_whitecube = NULL;
4027 r_texture_normalizationcube = NULL;
4028 r_texture_fogattenuation = NULL;
4029 r_texture_fogheighttexture = NULL;
4030 r_texture_gammaramps = NULL;
4031 r_texture_numcubemaps = 0;
4032 r_uniformbufferalignment = 32;
4034 r_loaddds = r_texture_dds_load.integer != 0;
4035 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
4037 switch(vid.renderpath)
4039 case RENDERPATH_GL20:
4040 case RENDERPATH_D3D9:
4041 case RENDERPATH_D3D10:
4042 case RENDERPATH_D3D11:
4043 case RENDERPATH_SOFT:
4044 case RENDERPATH_GLES2:
4045 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4046 Cvar_SetValueQuick(&gl_combine, 1);
4047 Cvar_SetValueQuick(&r_glsl, 1);
4048 r_loadnormalmap = true;
4051 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
4052 if (vid.support.arb_uniform_buffer_object)
4053 qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4056 case RENDERPATH_GL13:
4057 case RENDERPATH_GLES1:
4058 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4059 Cvar_SetValueQuick(&gl_combine, 1);
4060 Cvar_SetValueQuick(&r_glsl, 0);
4061 r_loadnormalmap = false;
4062 r_loadgloss = false;
4065 case RENDERPATH_GL11:
4066 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4067 Cvar_SetValueQuick(&gl_combine, 0);
4068 Cvar_SetValueQuick(&r_glsl, 0);
4069 r_loadnormalmap = false;
4070 r_loadgloss = false;
4076 R_FrameData_Reset();
4077 R_BufferData_Reset();
4081 memset(r_queries, 0, sizeof(r_queries));
4083 r_qwskincache = NULL;
4084 r_qwskincache_size = 0;
4086 // due to caching of texture_t references, the collision cache must be reset
4087 Collision_Cache_Reset(true);
4089 // set up r_skinframe loading system for textures
4090 memset(&r_skinframe, 0, sizeof(r_skinframe));
4091 r_skinframe.loadsequence = 1;
4092 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4094 r_main_texturepool = R_AllocTexturePool();
4095 R_BuildBlankTextures();
4097 if (vid.support.arb_texture_cube_map)
4100 R_BuildNormalizationCube();
4102 r_texture_fogattenuation = NULL;
4103 r_texture_fogheighttexture = NULL;
4104 r_texture_gammaramps = NULL;
4105 //r_texture_fogintensity = NULL;
4106 memset(&r_fb, 0, sizeof(r_fb));
4107 r_glsl_permutation = NULL;
4108 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4109 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4110 glslshaderstring = NULL;
4112 r_hlsl_permutation = NULL;
4113 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4114 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4116 hlslshaderstring = NULL;
4117 memset(&r_svbsp, 0, sizeof (r_svbsp));
4119 memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4120 r_texture_numcubemaps = 0;
4122 r_refdef.fogmasktable_density = 0;
4125 // For Steelstorm Android
4126 // FIXME CACHE the program and reload
4127 // FIXME see possible combinations for SS:BR android
4128 Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
4129 R_SetupShader_SetPermutationGLSL(0, 12);
4130 R_SetupShader_SetPermutationGLSL(0, 13);
4131 R_SetupShader_SetPermutationGLSL(0, 8388621);
4132 R_SetupShader_SetPermutationGLSL(3, 0);
4133 R_SetupShader_SetPermutationGLSL(3, 2048);
4134 R_SetupShader_SetPermutationGLSL(5, 0);
4135 R_SetupShader_SetPermutationGLSL(5, 2);
4136 R_SetupShader_SetPermutationGLSL(5, 2048);
4137 R_SetupShader_SetPermutationGLSL(5, 8388608);
4138 R_SetupShader_SetPermutationGLSL(11, 1);
4139 R_SetupShader_SetPermutationGLSL(11, 2049);
4140 R_SetupShader_SetPermutationGLSL(11, 8193);
4141 R_SetupShader_SetPermutationGLSL(11, 10241);
4142 Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
4146 static void gl_main_shutdown(void)
4149 R_FrameData_Reset();
4150 R_BufferData_Reset();
4152 R_Main_FreeViewCache();
4154 switch(vid.renderpath)
4156 case RENDERPATH_GL11:
4157 case RENDERPATH_GL13:
4158 case RENDERPATH_GL20:
4159 case RENDERPATH_GLES1:
4160 case RENDERPATH_GLES2:
4161 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
4163 qglDeleteQueriesARB(r_maxqueries, r_queries);
4166 case RENDERPATH_D3D9:
4167 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4169 case RENDERPATH_D3D10:
4170 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4172 case RENDERPATH_D3D11:
4173 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4175 case RENDERPATH_SOFT:
4181 memset(r_queries, 0, sizeof(r_queries));
4183 r_qwskincache = NULL;
4184 r_qwskincache_size = 0;
4186 // clear out the r_skinframe state
4187 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4188 memset(&r_skinframe, 0, sizeof(r_skinframe));
4191 Mem_Free(r_svbsp.nodes);
4192 memset(&r_svbsp, 0, sizeof (r_svbsp));
4193 R_FreeTexturePool(&r_main_texturepool);
4194 loadingscreentexture = NULL;
4195 r_texture_blanknormalmap = NULL;
4196 r_texture_white = NULL;
4197 r_texture_grey128 = NULL;
4198 r_texture_black = NULL;
4199 r_texture_whitecube = NULL;
4200 r_texture_normalizationcube = NULL;
4201 r_texture_fogattenuation = NULL;
4202 r_texture_fogheighttexture = NULL;
4203 r_texture_gammaramps = NULL;
4204 r_texture_numcubemaps = 0;
4205 //r_texture_fogintensity = NULL;
4206 memset(&r_fb, 0, sizeof(r_fb));
4209 r_glsl_permutation = NULL;
4210 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4211 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4212 glslshaderstring = NULL;
4214 r_hlsl_permutation = NULL;
4215 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4216 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4218 hlslshaderstring = NULL;
4221 static void gl_main_newmap(void)
4223 // FIXME: move this code to client
4224 char *entities, entname[MAX_QPATH];
4226 Mem_Free(r_qwskincache);
4227 r_qwskincache = NULL;
4228 r_qwskincache_size = 0;
4231 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4232 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4234 CL_ParseEntityLump(entities);
4238 if (cl.worldmodel->brush.entities)
4239 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4241 R_Main_FreeViewCache();
4243 R_FrameData_Reset();
4244 R_BufferData_Reset();
4247 void GL_Main_Init(void)
4250 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4252 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4253 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4254 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4255 if (gamemode == GAME_NEHAHRA)
4257 Cvar_RegisterVariable (&gl_fogenable);
4258 Cvar_RegisterVariable (&gl_fogdensity);
4259 Cvar_RegisterVariable (&gl_fogred);
4260 Cvar_RegisterVariable (&gl_foggreen);
4261 Cvar_RegisterVariable (&gl_fogblue);
4262 Cvar_RegisterVariable (&gl_fogstart);
4263 Cvar_RegisterVariable (&gl_fogend);
4264 Cvar_RegisterVariable (&gl_skyclip);
4266 Cvar_RegisterVariable(&r_motionblur);
4267 Cvar_RegisterVariable(&r_damageblur);
4268 Cvar_RegisterVariable(&r_motionblur_averaging);
4269 Cvar_RegisterVariable(&r_motionblur_randomize);
4270 Cvar_RegisterVariable(&r_motionblur_minblur);
4271 Cvar_RegisterVariable(&r_motionblur_maxblur);
4272 Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4273 Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4274 Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4275 Cvar_RegisterVariable(&r_motionblur_mousefactor);
4276 Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4277 Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4278 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4279 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4280 Cvar_RegisterVariable(&r_equalize_entities_by);
4281 Cvar_RegisterVariable(&r_equalize_entities_to);
4282 Cvar_RegisterVariable(&r_depthfirst);
4283 Cvar_RegisterVariable(&r_useinfinitefarclip);
4284 Cvar_RegisterVariable(&r_farclip_base);
4285 Cvar_RegisterVariable(&r_farclip_world);
4286 Cvar_RegisterVariable(&r_nearclip);
4287 Cvar_RegisterVariable(&r_deformvertexes);
4288 Cvar_RegisterVariable(&r_transparent);
4289 Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4290 Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4291 Cvar_RegisterVariable(&r_transparent_useplanardistance);
4292 Cvar_RegisterVariable(&r_showoverdraw);
4293 Cvar_RegisterVariable(&r_showbboxes);
4294 Cvar_RegisterVariable(&r_showsurfaces);
4295 Cvar_RegisterVariable(&r_showtris);
4296 Cvar_RegisterVariable(&r_shownormals);
4297 Cvar_RegisterVariable(&r_showlighting);
4298 Cvar_RegisterVariable(&r_showshadowvolumes);
4299 Cvar_RegisterVariable(&r_showcollisionbrushes);
4300 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4301 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4302 Cvar_RegisterVariable(&r_showdisabledepthtest);
4303 Cvar_RegisterVariable(&r_drawportals);
4304 Cvar_RegisterVariable(&r_drawentities);
4305 Cvar_RegisterVariable(&r_draw2d);
4306 Cvar_RegisterVariable(&r_drawworld);
4307 Cvar_RegisterVariable(&r_cullentities_trace);
4308 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4309 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4310 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4311 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4312 Cvar_RegisterVariable(&r_sortentities);
4313 Cvar_RegisterVariable(&r_drawviewmodel);
4314 Cvar_RegisterVariable(&r_drawexteriormodel);
4315 Cvar_RegisterVariable(&r_speeds);
4316 Cvar_RegisterVariable(&r_fullbrights);
4317 Cvar_RegisterVariable(&r_wateralpha);
4318 Cvar_RegisterVariable(&r_dynamic);
4319 Cvar_RegisterVariable(&r_fakelight);
4320 Cvar_RegisterVariable(&r_fakelight_intensity);
4321 Cvar_RegisterVariable(&r_fullbright);
4322 Cvar_RegisterVariable(&r_shadows);
4323 Cvar_RegisterVariable(&r_shadows_darken);
4324 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4325 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4326 Cvar_RegisterVariable(&r_shadows_throwdistance);
4327 Cvar_RegisterVariable(&r_shadows_throwdirection);
4328 Cvar_RegisterVariable(&r_shadows_focus);
4329 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4330 Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4331 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4332 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4333 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4334 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4335 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4336 Cvar_RegisterVariable(&r_fog_exp2);
4337 Cvar_RegisterVariable(&r_fog_clear);
4338 Cvar_RegisterVariable(&r_drawfog);
4339 Cvar_RegisterVariable(&r_transparentdepthmasking);
4340 Cvar_RegisterVariable(&r_transparent_sortmindist);
4341 Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4342 Cvar_RegisterVariable(&r_transparent_sortarraysize);
4343 Cvar_RegisterVariable(&r_texture_dds_load);
4344 Cvar_RegisterVariable(&r_texture_dds_save);
4345 Cvar_RegisterVariable(&r_textureunits);
4346 Cvar_RegisterVariable(&gl_combine);
4347 Cvar_RegisterVariable(&r_usedepthtextures);
4348 Cvar_RegisterVariable(&r_viewfbo);
4349 Cvar_RegisterVariable(&r_viewscale);
4350 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4351 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4352 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4353 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4354 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4355 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4356 Cvar_RegisterVariable(&r_glsl);
4357 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4358 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4359 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4360 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4361 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4362 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4363 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4364 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4365 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4366 Cvar_RegisterVariable(&r_glsl_postprocess);
4367 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4368 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4369 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4370 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4371 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4372 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4373 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4374 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4375 Cvar_RegisterVariable(&r_celshading);
4376 Cvar_RegisterVariable(&r_celoutlines);
4378 Cvar_RegisterVariable(&r_water);
4379 Cvar_RegisterVariable(&r_water_cameraentitiesonly);
4380 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4381 Cvar_RegisterVariable(&r_water_clippingplanebias);
4382 Cvar_RegisterVariable(&r_water_refractdistort);
4383 Cvar_RegisterVariable(&r_water_reflectdistort);
4384 Cvar_RegisterVariable(&r_water_scissormode);
4385 Cvar_RegisterVariable(&r_water_lowquality);
4386 Cvar_RegisterVariable(&r_water_hideplayer);
4387 Cvar_RegisterVariable(&r_water_fbo);
4389 Cvar_RegisterVariable(&r_lerpsprites);
4390 Cvar_RegisterVariable(&r_lerpmodels);
4391 Cvar_RegisterVariable(&r_lerplightstyles);
4392 Cvar_RegisterVariable(&r_waterscroll);
4393 Cvar_RegisterVariable(&r_bloom);
4394 Cvar_RegisterVariable(&r_bloom_colorscale);
4395 Cvar_RegisterVariable(&r_bloom_brighten);
4396 Cvar_RegisterVariable(&r_bloom_blur);
4397 Cvar_RegisterVariable(&r_bloom_resolution);
4398 Cvar_RegisterVariable(&r_bloom_colorexponent);
4399 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4400 Cvar_RegisterVariable(&r_bloom_scenebrightness);
4401 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4402 Cvar_RegisterVariable(&r_hdr_glowintensity);
4403 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4404 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4405 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4406 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4407 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4408 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4409 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4410 Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4411 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4412 Cvar_RegisterVariable(&developer_texturelogging);
4413 Cvar_RegisterVariable(&gl_lightmaps);
4414 Cvar_RegisterVariable(&r_test);
4415 Cvar_RegisterVariable(&r_batch_multidraw);
4416 Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4417 Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4418 Cvar_RegisterVariable(&r_glsl_skeletal);
4419 Cvar_RegisterVariable(&r_glsl_saturation);
4420 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4421 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4422 Cvar_RegisterVariable(&r_framedatasize);
4423 for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4424 Cvar_RegisterVariable(&r_buffermegs[i]);
4425 Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4426 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4427 Cvar_SetValue("r_fullbrights", 0);
4428 #ifdef DP_MOBILETOUCH
4429 // GLES devices have terrible depth precision in general, so...
4430 Cvar_SetValueQuick(&r_nearclip, 4);
4431 Cvar_SetValueQuick(&r_farclip_base, 4096);
4432 Cvar_SetValueQuick(&r_farclip_world, 0);
4433 Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
4435 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4438 void Render_Init(void)
4451 R_LightningBeams_Init();
4461 extern char *ENGINE_EXTENSIONS;
4464 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4465 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4466 gl_version = (const char *)qglGetString(GL_VERSION);
4467 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4471 if (!gl_platformextensions)
4472 gl_platformextensions = "";
4474 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4475 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4476 Con_Printf("GL_VERSION: %s\n", gl_version);
4477 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4478 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4480 VID_CheckExtensions();
4482 // LordHavoc: report supported extensions
4484 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4486 Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
4489 // clear to black (loading plaque will be seen over this)
4490 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4494 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4498 if (r_trippy.integer)
4500 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4502 p = r_refdef.view.frustum + i;
4507 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4511 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4515 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4519 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4523 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4527 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4531 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4535 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4543 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4547 if (r_trippy.integer)
4549 for (i = 0;i < numplanes;i++)
4556 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4560 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4564 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4568 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4572 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4576 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4580 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4584 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4592 //==================================================================================
4594 // LordHavoc: this stores temporary data used within the same frame
4596 typedef struct r_framedata_mem_s
4598 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4599 size_t size; // how much usable space
4600 size_t current; // how much space in use
4601 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4602 size_t wantedsize; // how much space was allocated
4603 unsigned char *data; // start of real data (16byte aligned)
4607 static r_framedata_mem_t *r_framedata_mem;
4609 void R_FrameData_Reset(void)
4611 while (r_framedata_mem)
4613 r_framedata_mem_t *next = r_framedata_mem->purge;
4614 Mem_Free(r_framedata_mem);
4615 r_framedata_mem = next;
4619 static void R_FrameData_Resize(qboolean mustgrow)
4622 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4623 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4624 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4626 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4627 newmem->wantedsize = wantedsize;
4628 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4629 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4630 newmem->current = 0;
4632 newmem->purge = r_framedata_mem;
4633 r_framedata_mem = newmem;
4637 void R_FrameData_NewFrame(void)
4639 R_FrameData_Resize(false);
4640 if (!r_framedata_mem)
4642 // if we ran out of space on the last frame, free the old memory now
4643 while (r_framedata_mem->purge)
4645 // repeatedly remove the second item in the list, leaving only head
4646 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4647 Mem_Free(r_framedata_mem->purge);
4648 r_framedata_mem->purge = next;
4650 // reset the current mem pointer
4651 r_framedata_mem->current = 0;
4652 r_framedata_mem->mark = 0;
4655 void *R_FrameData_Alloc(size_t size)
4660 // align to 16 byte boundary - the data pointer is already aligned, so we
4661 // only need to ensure the size of every allocation is also aligned
4662 size = (size + 15) & ~15;
4664 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4666 // emergency - we ran out of space, allocate more memory
4667 newvalue = bound(0.25f, r_framedatasize.value * 2.0f, 256.0f);
4668 // this might not be a growing it, but we'll allocate another buffer every time
4669 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4670 R_FrameData_Resize(true);
4673 data = r_framedata_mem->data + r_framedata_mem->current;
4674 r_framedata_mem->current += size;
4676 // count the usage for stats
4677 r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4678 r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4680 return (void *)data;
4683 void *R_FrameData_Store(size_t size, void *data)
4685 void *d = R_FrameData_Alloc(size);
4687 memcpy(d, data, size);
4691 void R_FrameData_SetMark(void)
4693 if (!r_framedata_mem)
4695 r_framedata_mem->mark = r_framedata_mem->current;
4698 void R_FrameData_ReturnToMark(void)
4700 if (!r_framedata_mem)
4702 r_framedata_mem->current = r_framedata_mem->mark;
4705 //==================================================================================
4707 // avoid reusing the same buffer objects on consecutive frames
4708 #define R_BUFFERDATA_CYCLE 3
4710 typedef struct r_bufferdata_buffer_s
4712 struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4713 size_t size; // how much usable space
4714 size_t current; // how much space in use
4715 r_meshbuffer_t *buffer; // the buffer itself
4717 r_bufferdata_buffer_t;
4719 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4720 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4722 /// frees all dynamic buffers
4723 void R_BufferData_Reset(void)
4726 r_bufferdata_buffer_t **p, *mem;
4727 for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4729 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4732 p = &r_bufferdata_buffer[cycle][type];
4738 R_Mesh_DestroyMeshBuffer(mem->buffer);
4745 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4746 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4748 r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4750 float newvalue = r_buffermegs[type].value;
4752 // increase the cvar if we have to (but only if we already have a mem)
4753 if (mustgrow && mem)
4755 newvalue = bound(0.25f, newvalue, 256.0f);
4756 while (newvalue * 1024*1024 < minsize)
4759 // clamp the cvar to valid range
4760 newvalue = bound(0.25f, newvalue, 256.0f);
4761 if (r_buffermegs[type].value != newvalue)
4762 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4764 // calculate size in bytes
4765 size = (size_t)(newvalue * 1024*1024);
4766 size = bound(131072, size, 256*1024*1024);
4768 // allocate a new buffer if the size is different (purge old one later)
4769 // or if we were told we must grow the buffer
4770 if (!mem || mem->size != size || mustgrow)
4772 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4775 if (type == R_BUFFERDATA_VERTEX)
4776 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4777 else if (type == R_BUFFERDATA_INDEX16)
4778 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4779 else if (type == R_BUFFERDATA_INDEX32)
4780 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4781 else if (type == R_BUFFERDATA_UNIFORM)
4782 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4783 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4784 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4788 void R_BufferData_NewFrame(void)
4791 r_bufferdata_buffer_t **p, *mem;
4792 // cycle to the next frame's buffers
4793 r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4794 // if we ran out of space on the last time we used these buffers, free the old memory now
4795 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4797 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4799 R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4800 // free all but the head buffer, this is how we recycle obsolete
4801 // buffers after they are no longer in use
4802 p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4808 R_Mesh_DestroyMeshBuffer(mem->buffer);
4811 // reset the current offset
4812 r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4817 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4819 r_bufferdata_buffer_t *mem;
4823 *returnbufferoffset = 0;
4825 // align size to a byte boundary appropriate for the buffer type, this
4826 // makes all allocations have aligned start offsets
4827 if (type == R_BUFFERDATA_UNIFORM)
4828 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4830 padsize = (datasize + 15) & ~15;
4832 // if we ran out of space in this buffer we must allocate a new one
4833 if (!r_bufferdata_buffer[r_bufferdata_cycle][type] || r_bufferdata_buffer[r_bufferdata_cycle][type]->current + padsize > r_bufferdata_buffer[r_bufferdata_cycle][type]->size)
4834 R_BufferData_Resize(type, true, padsize);
4836 // if the resize did not give us enough memory, fail
4837 if (!r_bufferdata_buffer[r_bufferdata_cycle][type] || r_bufferdata_buffer[r_bufferdata_cycle][type]->current + padsize > r_bufferdata_buffer[r_bufferdata_cycle][type]->size)
4838 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4840 mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4841 offset = (int)mem->current;
4842 mem->current += padsize;
4844 // upload the data to the buffer at the chosen offset
4846 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4847 R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4849 // count the usage for stats
4850 r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4851 r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4853 // return the buffer offset
4854 *returnbufferoffset = offset;
4859 //==================================================================================
4861 // LordHavoc: animcache originally written by Echon, rewritten since then
4864 * Animation cache prevents re-generating mesh data for an animated model
4865 * multiple times in one frame for lighting, shadowing, reflections, etc.
4868 void R_AnimCache_Free(void)
4872 void R_AnimCache_ClearCache(void)
4875 entity_render_t *ent;
4877 for (i = 0;i < r_refdef.scene.numentities;i++)
4879 ent = r_refdef.scene.entities[i];
4880 ent->animcache_vertex3f = NULL;
4881 ent->animcache_vertex3f_vertexbuffer = NULL;
4882 ent->animcache_vertex3f_bufferoffset = 0;
4883 ent->animcache_normal3f = NULL;
4884 ent->animcache_normal3f_vertexbuffer = NULL;
4885 ent->animcache_normal3f_bufferoffset = 0;
4886 ent->animcache_svector3f = NULL;
4887 ent->animcache_svector3f_vertexbuffer = NULL;
4888 ent->animcache_svector3f_bufferoffset = 0;
4889 ent->animcache_tvector3f = NULL;
4890 ent->animcache_tvector3f_vertexbuffer = NULL;
4891 ent->animcache_tvector3f_bufferoffset = 0;
4892 ent->animcache_vertexmesh = NULL;
4893 ent->animcache_vertexmesh_vertexbuffer = NULL;
4894 ent->animcache_vertexmesh_bufferoffset = 0;
4895 ent->animcache_skeletaltransform3x4 = NULL;
4896 ent->animcache_skeletaltransform3x4buffer = NULL;
4897 ent->animcache_skeletaltransform3x4offset = 0;
4898 ent->animcache_skeletaltransform3x4size = 0;
4902 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4906 // check if we need the meshbuffers
4907 if (!vid.useinterleavedarrays)
4910 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4911 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4912 // TODO: upload vertexbuffer?
4913 if (ent->animcache_vertexmesh)
4915 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4916 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4917 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4918 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4919 for (i = 0;i < numvertices;i++)
4920 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4921 if (ent->animcache_svector3f)
4922 for (i = 0;i < numvertices;i++)
4923 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4924 if (ent->animcache_tvector3f)
4925 for (i = 0;i < numvertices;i++)
4926 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4927 if (ent->animcache_normal3f)
4928 for (i = 0;i < numvertices;i++)
4929 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4933 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4935 dp_model_t *model = ent->model;
4938 // see if this ent is worth caching
4939 if (!model || !model->Draw || !model->AnimateVertices)
4941 // nothing to cache if it contains no animations and has no skeleton
4942 if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4944 // see if it is already cached for gpuskeletal
4945 if (ent->animcache_skeletaltransform3x4)
4947 // see if it is already cached as a mesh
4948 if (ent->animcache_vertex3f)
4950 // check if we need to add normals or tangents
4951 if (ent->animcache_normal3f)
4952 wantnormals = false;
4953 if (ent->animcache_svector3f)
4954 wanttangents = false;
4955 if (!wantnormals && !wanttangents)
4959 // check which kind of cache we need to generate
4960 if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4962 // cache the skeleton so the vertex shader can use it
4963 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
4964 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
4965 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
4966 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4967 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4);
4968 // note: this can fail if the buffer is at the grow limit
4969 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
4970 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
4972 else if (ent->animcache_vertex3f)
4974 // mesh was already cached but we may need to add normals/tangents
4975 // (this only happens with multiple views, reflections, cameras, etc)
4976 if (wantnormals || wanttangents)
4978 numvertices = model->surfmesh.num_vertices;
4980 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4983 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4984 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4986 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4987 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4988 r_refdef.stats[r_stat_animcache_shade_count] += 1;
4989 r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4990 r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4995 // generate mesh cache
4996 numvertices = model->surfmesh.num_vertices;
4997 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4999 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5002 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5003 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5005 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
5006 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5007 if (wantnormals || wanttangents)
5009 r_refdef.stats[r_stat_animcache_shade_count] += 1;
5010 r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5011 r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5013 r_refdef.stats[r_stat_animcache_shape_count] += 1;
5014 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
5015 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
5020 void R_AnimCache_CacheVisibleEntities(void)
5023 qboolean wantnormals = true;
5024 qboolean wanttangents = !r_showsurfaces.integer;
5026 switch(vid.renderpath)
5028 case RENDERPATH_GL20:
5029 case RENDERPATH_D3D9:
5030 case RENDERPATH_D3D10:
5031 case RENDERPATH_D3D11:
5032 case RENDERPATH_GLES2:
5034 case RENDERPATH_GL11:
5035 case RENDERPATH_GL13:
5036 case RENDERPATH_GLES1:
5037 wanttangents = false;
5039 case RENDERPATH_SOFT:
5043 if (r_shownormals.integer)
5044 wanttangents = wantnormals = true;
5046 // TODO: thread this
5047 // NOTE: R_PrepareRTLights() also caches entities
5049 for (i = 0;i < r_refdef.scene.numentities;i++)
5050 if (r_refdef.viewcache.entityvisible[i])
5051 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5054 //==================================================================================
5056 extern cvar_t r_overheadsprites_pushback;
5058 static void R_View_UpdateEntityLighting (void)
5061 entity_render_t *ent;
5062 vec3_t tempdiffusenormal, avg;
5063 vec_t f, fa, fd, fdd;
5064 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
5066 for (i = 0;i < r_refdef.scene.numentities;i++)
5068 ent = r_refdef.scene.entities[i];
5070 // skip unseen models
5071 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
5075 if (ent->model && ent->model == cl.worldmodel)
5077 // TODO: use modellight for r_ambient settings on world?
5078 VectorSet(ent->modellight_ambient, 0, 0, 0);
5079 VectorSet(ent->modellight_diffuse, 0, 0, 0);
5080 VectorSet(ent->modellight_lightdir, 0, 0, 1);
5084 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
5086 // aleady updated by CSQC
5087 // TODO: force modellight on BSP models in this case?
5088 VectorCopy(ent->modellight_lightdir, tempdiffusenormal);
5092 // fetch the lighting from the worldmodel data
5093 VectorClear(ent->modellight_ambient);
5094 VectorClear(ent->modellight_diffuse);
5095 VectorClear(tempdiffusenormal);
5096 if (ent->flags & RENDER_LIGHT)
5099 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5101 // complete lightning for lit sprites
5102 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
5103 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
5105 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
5106 org[2] = org[2] + r_overheadsprites_pushback.value;
5107 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5110 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
5112 if(ent->flags & RENDER_EQUALIZE)
5114 // first fix up ambient lighting...
5115 if(r_equalize_entities_minambient.value > 0)
5117 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5120 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
5121 if(fa < r_equalize_entities_minambient.value * fd)
5124 // fa'/fd' = minambient
5125 // fa'+0.25*fd' = fa+0.25*fd
5127 // fa' = fd' * minambient
5128 // fd'*(0.25+minambient) = fa+0.25*fd
5130 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
5131 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
5133 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
5134 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
5135 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
5136 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
5141 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
5143 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
5144 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5148 // adjust brightness and saturation to target
5149 avg[0] = avg[1] = avg[2] = fa / f;
5150 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
5151 avg[0] = avg[1] = avg[2] = fd / f;
5152 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
5158 VectorSet(ent->modellight_ambient, 1, 1, 1);
5161 // move the light direction into modelspace coordinates for lighting code
5162 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
5163 if(VectorLength2(ent->modellight_lightdir) == 0)
5164 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
5165 VectorNormalize(ent->modellight_lightdir);
5169 #define MAX_LINEOFSIGHTTRACES 64
5171 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5174 vec3_t boxmins, boxmaxs;
5177 dp_model_t *model = r_refdef.scene.worldmodel;
5179 if (!model || !model->brush.TraceLineOfSight)
5182 // expand the box a little
5183 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
5184 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
5185 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
5186 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
5187 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
5188 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
5190 // return true if eye is inside enlarged box
5191 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
5195 VectorCopy(eye, start);
5196 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
5197 if (model->brush.TraceLineOfSight(model, start, end))
5200 // try various random positions
5201 for (i = 0;i < numsamples;i++)
5203 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5204 if (model->brush.TraceLineOfSight(model, start, end))
5212 static void R_View_UpdateEntityVisible (void)
5217 entity_render_t *ent;
5219 if (r_refdef.envmap || r_fb.water.hideplayer)
5220 renderimask = RENDER_EXTERIORMODEL | RENDER_VIEWMODEL;
5221 else if (chase_active.integer || r_fb.water.renderingscene)
5222 renderimask = RENDER_VIEWMODEL;
5224 renderimask = RENDER_EXTERIORMODEL;
5225 if (!r_drawviewmodel.integer)
5226 renderimask |= RENDER_VIEWMODEL;
5227 if (!r_drawexteriormodel.integer)
5228 renderimask |= RENDER_EXTERIORMODEL;
5229 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5230 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5232 // worldmodel can check visibility
5233 for (i = 0;i < r_refdef.scene.numentities;i++)
5235 ent = r_refdef.scene.entities[i];
5236 if (!(ent->flags & renderimask))
5237 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)))
5238 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))
5239 r_refdef.viewcache.entityvisible[i] = true;
5244 // no worldmodel or it can't check visibility
5245 for (i = 0;i < r_refdef.scene.numentities;i++)
5247 ent = r_refdef.scene.entities[i];
5248 if (!(ent->flags & renderimask))
5249 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)))
5250 r_refdef.viewcache.entityvisible[i] = true;
5253 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
5254 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
5256 for (i = 0;i < r_refdef.scene.numentities;i++)
5258 if (!r_refdef.viewcache.entityvisible[i])
5260 ent = r_refdef.scene.entities[i];
5261 if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5263 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
5265 continue; // temp entities do pvs only
5266 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5267 ent->last_trace_visibility = realtime;
5268 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5269 r_refdef.viewcache.entityvisible[i] = 0;
5275 /// only used if skyrendermasked, and normally returns false
5276 static int R_DrawBrushModelsSky (void)
5279 entity_render_t *ent;
5282 for (i = 0;i < r_refdef.scene.numentities;i++)
5284 if (!r_refdef.viewcache.entityvisible[i])
5286 ent = r_refdef.scene.entities[i];
5287 if (!ent->model || !ent->model->DrawSky)
5289 ent->model->DrawSky(ent);
5295 static void R_DrawNoModel(entity_render_t *ent);
5296 static void R_DrawModels(void)
5299 entity_render_t *ent;
5301 for (i = 0;i < r_refdef.scene.numentities;i++)
5303 if (!r_refdef.viewcache.entityvisible[i])
5305 ent = r_refdef.scene.entities[i];
5306 r_refdef.stats[r_stat_entities]++;
5308 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5311 Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5312 Con_Printf("R_DrawModels\n");
5313 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]);
5314 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);
5315 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);
5318 if (ent->model && ent->model->Draw != NULL)
5319 ent->model->Draw(ent);
5325 static void R_DrawModelsDepth(void)
5328 entity_render_t *ent;
5330 for (i = 0;i < r_refdef.scene.numentities;i++)
5332 if (!r_refdef.viewcache.entityvisible[i])
5334 ent = r_refdef.scene.entities[i];
5335 if (ent->model && ent->model->DrawDepth != NULL)
5336 ent->model->DrawDepth(ent);
5340 static void R_DrawModelsDebug(void)
5343 entity_render_t *ent;
5345 for (i = 0;i < r_refdef.scene.numentities;i++)
5347 if (!r_refdef.viewcache.entityvisible[i])
5349 ent = r_refdef.scene.entities[i];
5350 if (ent->model && ent->model->DrawDebug != NULL)
5351 ent->model->DrawDebug(ent);
5355 static void R_DrawModelsAddWaterPlanes(void)
5358 entity_render_t *ent;
5360 for (i = 0;i < r_refdef.scene.numentities;i++)
5362 if (!r_refdef.viewcache.entityvisible[i])
5364 ent = r_refdef.scene.entities[i];
5365 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5366 ent->model->DrawAddWaterPlanes(ent);
5370 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}};
5372 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5374 if (r_hdr_irisadaptation.integer)
5379 vec3_t diffusenormal;
5381 vec_t brightness = 0.0f;
5386 VectorCopy(r_refdef.view.forward, forward);
5387 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5389 p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5390 p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5391 p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5392 R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5393 d = DotProduct(forward, diffusenormal);
5394 brightness += VectorLength(ambient);
5396 brightness += d * VectorLength(diffuse);
5398 brightness *= 1.0f / c;
5399 brightness += 0.00001f; // make sure it's never zero
5400 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5401 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5402 current = r_hdr_irisadaptation_value.value;
5404 current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5405 else if (current > goal)
5406 current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5407 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5408 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5410 else if (r_hdr_irisadaptation_value.value != 1.0f)
5411 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5414 static void R_View_SetFrustum(const int *scissor)
5417 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5418 vec3_t forward, left, up, origin, v;
5422 // flipped x coordinates (because x points left here)
5423 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5424 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5426 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5427 switch(vid.renderpath)
5429 case RENDERPATH_D3D9:
5430 case RENDERPATH_D3D10:
5431 case RENDERPATH_D3D11:
5432 // non-flipped y coordinates
5433 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5434 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5436 case RENDERPATH_SOFT:
5437 case RENDERPATH_GL11:
5438 case RENDERPATH_GL13:
5439 case RENDERPATH_GL20:
5440 case RENDERPATH_GLES1:
5441 case RENDERPATH_GLES2:
5442 // non-flipped y coordinates
5443 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5444 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5449 // we can't trust r_refdef.view.forward and friends in reflected scenes
5450 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5453 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5454 r_refdef.view.frustum[0].normal[1] = 0 - 0;
5455 r_refdef.view.frustum[0].normal[2] = -1 - 0;
5456 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5457 r_refdef.view.frustum[1].normal[1] = 0 + 0;
5458 r_refdef.view.frustum[1].normal[2] = -1 + 0;
5459 r_refdef.view.frustum[2].normal[0] = 0 - 0;
5460 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5461 r_refdef.view.frustum[2].normal[2] = -1 - 0;
5462 r_refdef.view.frustum[3].normal[0] = 0 + 0;
5463 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5464 r_refdef.view.frustum[3].normal[2] = -1 + 0;
5468 zNear = r_refdef.nearclip;
5469 nudge = 1.0 - 1.0 / (1<<23);
5470 r_refdef.view.frustum[4].normal[0] = 0 - 0;
5471 r_refdef.view.frustum[4].normal[1] = 0 - 0;
5472 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5473 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5474 r_refdef.view.frustum[5].normal[0] = 0 + 0;
5475 r_refdef.view.frustum[5].normal[1] = 0 + 0;
5476 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5477 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5483 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5484 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5485 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5486 r_refdef.view.frustum[0].dist = m[15] - m[12];
5488 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5489 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5490 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5491 r_refdef.view.frustum[1].dist = m[15] + m[12];
5493 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5494 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5495 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5496 r_refdef.view.frustum[2].dist = m[15] - m[13];
5498 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5499 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5500 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5501 r_refdef.view.frustum[3].dist = m[15] + m[13];
5503 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5504 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5505 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5506 r_refdef.view.frustum[4].dist = m[15] - m[14];
5508 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5509 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5510 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5511 r_refdef.view.frustum[5].dist = m[15] + m[14];
5514 if (r_refdef.view.useperspective)
5516 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5517 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]);
5518 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]);
5519 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]);
5520 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]);
5522 // then the normals from the corners relative to origin
5523 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5524 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5525 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5526 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5528 // in a NORMAL view, forward cross left == up
5529 // in a REFLECTED view, forward cross left == down
5530 // so our cross products above need to be adjusted for a left handed coordinate system
5531 CrossProduct(forward, left, v);
5532 if(DotProduct(v, up) < 0)
5534 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5535 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5536 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5537 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5540 // Leaving those out was a mistake, those were in the old code, and they
5541 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5542 // I couldn't reproduce it after adding those normalizations. --blub
5543 VectorNormalize(r_refdef.view.frustum[0].normal);
5544 VectorNormalize(r_refdef.view.frustum[1].normal);
5545 VectorNormalize(r_refdef.view.frustum[2].normal);
5546 VectorNormalize(r_refdef.view.frustum[3].normal);
5548 // make the corners absolute
5549 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5550 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5551 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5552 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5555 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5557 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5558 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5559 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5560 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5561 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5565 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5566 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5567 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5568 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5569 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5570 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5571 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5572 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5573 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5574 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5576 r_refdef.view.numfrustumplanes = 5;
5578 if (r_refdef.view.useclipplane)
5580 r_refdef.view.numfrustumplanes = 6;
5581 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5584 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5585 PlaneClassify(r_refdef.view.frustum + i);
5587 // LordHavoc: note to all quake engine coders, Quake had a special case
5588 // for 90 degrees which assumed a square view (wrong), so I removed it,
5589 // Quake2 has it disabled as well.
5591 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5592 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5593 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5594 //PlaneClassify(&frustum[0]);
5596 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5597 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5598 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5599 //PlaneClassify(&frustum[1]);
5601 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5602 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5603 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5604 //PlaneClassify(&frustum[2]);
5606 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5607 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5608 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5609 //PlaneClassify(&frustum[3]);
5612 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5613 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5614 //PlaneClassify(&frustum[4]);
5617 static void R_View_UpdateWithScissor(const int *myscissor)
5619 R_Main_ResizeViewCache();
5620 R_View_SetFrustum(myscissor);
5621 R_View_WorldVisibility(r_refdef.view.useclipplane);
5622 R_View_UpdateEntityVisible();
5623 R_View_UpdateEntityLighting();
5626 static void R_View_Update(void)
5628 R_Main_ResizeViewCache();
5629 R_View_SetFrustum(NULL);
5630 R_View_WorldVisibility(r_refdef.view.useclipplane);
5631 R_View_UpdateEntityVisible();
5632 R_View_UpdateEntityLighting();
5635 float viewscalefpsadjusted = 1.0f;
5637 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5639 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5640 scale = bound(0.03125f, scale, 1.0f);
5641 *outwidth = (int)ceil(width * scale);
5642 *outheight = (int)ceil(height * scale);
5645 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5647 const float *customclipplane = NULL;
5649 int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5650 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5652 // LordHavoc: couldn't figure out how to make this approach the
5653 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5654 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5655 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5656 dist = r_refdef.view.clipplane.dist;
5657 plane[0] = r_refdef.view.clipplane.normal[0];
5658 plane[1] = r_refdef.view.clipplane.normal[1];
5659 plane[2] = r_refdef.view.clipplane.normal[2];
5661 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5664 //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5665 rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5667 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5668 if (!r_refdef.view.useperspective)
5669 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);
5670 else if (vid.stencil && r_useinfinitefarclip.integer)
5671 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);
5673 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);
5674 R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5675 R_SetViewport(&r_refdef.view.viewport);
5676 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5678 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5679 float screenplane[4];
5680 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5681 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5682 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5683 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5684 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5688 void R_EntityMatrix(const matrix4x4_t *matrix)
5690 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5692 gl_modelmatrixchanged = false;
5693 gl_modelmatrix = *matrix;
5694 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5695 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5696 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5697 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5699 switch(vid.renderpath)
5701 case RENDERPATH_D3D9:
5703 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5704 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5707 case RENDERPATH_D3D10:
5708 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5710 case RENDERPATH_D3D11:
5711 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5713 case RENDERPATH_GL11:
5714 case RENDERPATH_GL13:
5715 case RENDERPATH_GLES1:
5717 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5720 case RENDERPATH_SOFT:
5721 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5722 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5724 case RENDERPATH_GL20:
5725 case RENDERPATH_GLES2:
5726 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5727 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5733 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5735 r_viewport_t viewport;
5739 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5740 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);
5741 R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5742 R_SetViewport(&viewport);
5743 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5744 GL_Color(1, 1, 1, 1);
5745 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5746 GL_BlendFunc(GL_ONE, GL_ZERO);
5747 GL_ScissorTest(false);
5748 GL_DepthMask(false);
5749 GL_DepthRange(0, 1);
5750 GL_DepthTest(false);
5751 GL_DepthFunc(GL_LEQUAL);
5752 R_EntityMatrix(&identitymatrix);
5753 R_Mesh_ResetTextureState();
5754 GL_PolygonOffset(0, 0);
5755 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5756 switch(vid.renderpath)
5758 case RENDERPATH_GL11:
5759 case RENDERPATH_GL13:
5760 case RENDERPATH_GL20:
5761 case RENDERPATH_GLES1:
5762 case RENDERPATH_GLES2:
5763 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5765 case RENDERPATH_D3D9:
5766 case RENDERPATH_D3D10:
5767 case RENDERPATH_D3D11:
5768 case RENDERPATH_SOFT:
5771 GL_CullFace(GL_NONE);
5776 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5780 R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5783 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5787 R_SetupView(true, fbo, depthtexture, colortexture);
5788 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5789 GL_Color(1, 1, 1, 1);
5790 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5791 GL_BlendFunc(GL_ONE, GL_ZERO);
5792 GL_ScissorTest(true);
5794 GL_DepthRange(0, 1);
5796 GL_DepthFunc(GL_LEQUAL);
5797 R_EntityMatrix(&identitymatrix);
5798 R_Mesh_ResetTextureState();
5799 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5800 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5801 switch(vid.renderpath)
5803 case RENDERPATH_GL11:
5804 case RENDERPATH_GL13:
5805 case RENDERPATH_GL20:
5806 case RENDERPATH_GLES1:
5807 case RENDERPATH_GLES2:
5808 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5810 case RENDERPATH_D3D9:
5811 case RENDERPATH_D3D10:
5812 case RENDERPATH_D3D11:
5813 case RENDERPATH_SOFT:
5816 GL_CullFace(r_refdef.view.cullface_back);
5821 R_RenderView_UpdateViewVectors
5824 void R_RenderView_UpdateViewVectors(void)
5826 // break apart the view matrix into vectors for various purposes
5827 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5828 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5829 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5830 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5831 // make an inverted copy of the view matrix for tracking sprites
5832 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5835 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5836 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5838 static void R_Water_StartFrame(void)
5841 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5842 r_waterstate_waterplane_t *p;
5843 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;
5845 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5848 switch(vid.renderpath)
5850 case RENDERPATH_GL20:
5851 case RENDERPATH_D3D9:
5852 case RENDERPATH_D3D10:
5853 case RENDERPATH_D3D11:
5854 case RENDERPATH_SOFT:
5855 case RENDERPATH_GLES2:
5857 case RENDERPATH_GL11:
5858 case RENDERPATH_GL13:
5859 case RENDERPATH_GLES1:
5863 // set waterwidth and waterheight to the water resolution that will be
5864 // used (often less than the screen resolution for faster rendering)
5865 R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5867 // calculate desired texture sizes
5868 // can't use water if the card does not support the texture size
5869 if (!r_water.integer || r_showsurfaces.integer)
5870 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5871 else if (vid.support.arb_texture_non_power_of_two)
5873 texturewidth = waterwidth;
5874 textureheight = waterheight;
5875 camerawidth = waterwidth;
5876 cameraheight = waterheight;
5880 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5881 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5882 for (camerawidth = 1;camerawidth * 2 <= waterwidth ;camerawidth *= 2);
5883 for (cameraheight = 1;cameraheight * 2 <= waterheight;cameraheight *= 2);
5886 // allocate textures as needed
5887 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))
5889 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5890 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5892 if (p->texture_refraction)
5893 R_FreeTexture(p->texture_refraction);
5894 p->texture_refraction = NULL;
5895 if (p->fbo_refraction)
5896 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5897 p->fbo_refraction = 0;
5898 if (p->texture_reflection)
5899 R_FreeTexture(p->texture_reflection);
5900 p->texture_reflection = NULL;
5901 if (p->fbo_reflection)
5902 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5903 p->fbo_reflection = 0;
5904 if (p->texture_camera)
5905 R_FreeTexture(p->texture_camera);
5906 p->texture_camera = NULL;
5908 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5911 memset(&r_fb.water, 0, sizeof(r_fb.water));
5912 r_fb.water.texturewidth = texturewidth;
5913 r_fb.water.textureheight = textureheight;
5914 r_fb.water.camerawidth = camerawidth;
5915 r_fb.water.cameraheight = cameraheight;
5918 if (r_fb.water.texturewidth)
5920 int scaledwidth, scaledheight;
5922 r_fb.water.enabled = true;
5924 // water resolution is usually reduced
5925 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5926 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5927 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5929 // set up variables that will be used in shader setup
5930 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5931 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5932 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5933 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5936 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5937 r_fb.water.numwaterplanes = 0;
5940 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5942 int planeindex, bestplaneindex, vertexindex;
5943 vec3_t mins, maxs, normal, center, v, n;
5944 vec_t planescore, bestplanescore;
5946 r_waterstate_waterplane_t *p;
5947 texture_t *t = R_GetCurrentTexture(surface->texture);
5949 rsurface.texture = t;
5950 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5951 // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5952 if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5954 // average the vertex normals, find the surface bounds (after deformvertexes)
5955 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5956 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5957 VectorCopy(n, normal);
5958 VectorCopy(v, mins);
5959 VectorCopy(v, maxs);
5960 for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5962 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5963 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5964 VectorAdd(normal, n, normal);
5965 mins[0] = min(mins[0], v[0]);
5966 mins[1] = min(mins[1], v[1]);
5967 mins[2] = min(mins[2], v[2]);
5968 maxs[0] = max(maxs[0], v[0]);
5969 maxs[1] = max(maxs[1], v[1]);
5970 maxs[2] = max(maxs[2], v[2]);
5972 VectorNormalize(normal);
5973 VectorMAM(0.5f, mins, 0.5f, maxs, center);
5975 VectorCopy(normal, plane.normal);
5976 VectorNormalize(plane.normal);
5977 plane.dist = DotProduct(center, plane.normal);
5978 PlaneClassify(&plane);
5979 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5981 // skip backfaces (except if nocullface is set)
5982 // if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5984 VectorNegate(plane.normal, plane.normal);
5986 PlaneClassify(&plane);
5990 // find a matching plane if there is one
5991 bestplaneindex = -1;
5992 bestplanescore = 1048576.0f;
5993 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5995 if(p->camera_entity == t->camera_entity)
5997 planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5998 if (bestplaneindex < 0 || bestplanescore > planescore)
6000 bestplaneindex = planeindex;
6001 bestplanescore = planescore;
6005 planeindex = bestplaneindex;
6007 // if this surface does not fit any known plane rendered this frame, add one
6008 if (planeindex < 0 || bestplanescore > 0.001f)
6010 if (r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
6012 // store the new plane
6013 planeindex = r_fb.water.numwaterplanes++;
6014 p = r_fb.water.waterplanes + planeindex;
6016 // clear materialflags and pvs
6017 p->materialflags = 0;
6018 p->pvsvalid = false;
6019 p->camera_entity = t->camera_entity;
6020 VectorCopy(mins, p->mins);
6021 VectorCopy(maxs, p->maxs);
6025 // We're totally screwed.
6031 // merge mins/maxs when we're adding this surface to the plane
6032 p = r_fb.water.waterplanes + planeindex;
6033 p->mins[0] = min(p->mins[0], mins[0]);
6034 p->mins[1] = min(p->mins[1], mins[1]);
6035 p->mins[2] = min(p->mins[2], mins[2]);
6036 p->maxs[0] = max(p->maxs[0], maxs[0]);
6037 p->maxs[1] = max(p->maxs[1], maxs[1]);
6038 p->maxs[2] = max(p->maxs[2], maxs[2]);
6040 // merge this surface's materialflags into the waterplane
6041 p->materialflags |= t->currentmaterialflags;
6042 if(!(p->materialflags & MATERIALFLAG_CAMERA))
6044 // merge this surface's PVS into the waterplane
6045 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6046 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6048 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6054 extern cvar_t r_drawparticles;
6055 extern cvar_t r_drawdecals;
6057 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6060 r_refdef_view_t originalview;
6061 r_refdef_view_t myview;
6062 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;
6063 r_waterstate_waterplane_t *p;
6065 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;
6068 originalview = r_refdef.view;
6070 // lowquality hack, temporarily shut down some cvars and restore afterwards
6071 qualityreduction = r_water_lowquality.integer;
6072 if (qualityreduction > 0)
6074 if (qualityreduction >= 1)
6076 old_r_shadows = r_shadows.integer;
6077 old_r_worldrtlight = r_shadow_realtime_world.integer;
6078 old_r_dlight = r_shadow_realtime_dlight.integer;
6079 Cvar_SetValueQuick(&r_shadows, 0);
6080 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6081 Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6083 if (qualityreduction >= 2)
6085 old_r_dynamic = r_dynamic.integer;
6086 old_r_particles = r_drawparticles.integer;
6087 old_r_decals = r_drawdecals.integer;
6088 Cvar_SetValueQuick(&r_dynamic, 0);
6089 Cvar_SetValueQuick(&r_drawparticles, 0);
6090 Cvar_SetValueQuick(&r_drawdecals, 0);
6094 // make sure enough textures are allocated
6095 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6097 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6099 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6101 if (!p->texture_refraction)
6102 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);
6103 if (!p->texture_refraction)
6107 if (r_fb.water.depthtexture == NULL)
6108 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6109 if (p->fbo_refraction == 0)
6110 p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6113 else if (p->materialflags & MATERIALFLAG_CAMERA)
6115 if (!p->texture_camera)
6116 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);
6117 if (!p->texture_camera)
6121 if (r_fb.water.depthtexture == NULL)
6122 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6123 if (p->fbo_camera == 0)
6124 p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6128 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6130 if (!p->texture_reflection)
6131 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);
6132 if (!p->texture_reflection)
6136 if (r_fb.water.depthtexture == NULL)
6137 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6138 if (p->fbo_reflection == 0)
6139 p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6145 r_refdef.view = originalview;
6146 r_refdef.view.showdebug = false;
6147 r_refdef.view.width = r_fb.water.waterwidth;
6148 r_refdef.view.height = r_fb.water.waterheight;
6149 r_refdef.view.useclipplane = true;
6150 myview = r_refdef.view;
6151 r_fb.water.renderingscene = true;
6152 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6154 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6156 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6158 r_refdef.view = myview;
6159 if(r_water_scissormode.integer)
6161 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6162 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6163 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6166 // render reflected scene and copy into texture
6167 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6168 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6169 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6170 r_refdef.view.clipplane = p->plane;
6171 // reverse the cullface settings for this render
6172 r_refdef.view.cullface_front = GL_FRONT;
6173 r_refdef.view.cullface_back = GL_BACK;
6174 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6176 r_refdef.view.usecustompvs = true;
6178 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6180 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6183 r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
6184 R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6185 R_ClearScreen(r_refdef.fogenabled);
6186 if(r_water_scissormode.integer & 2)
6187 R_View_UpdateWithScissor(myscissor);
6190 R_AnimCache_CacheVisibleEntities();
6191 if(r_water_scissormode.integer & 1)
6192 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6193 R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6195 if (!p->fbo_reflection)
6196 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);
6197 r_fb.water.hideplayer = false;
6200 // render the normal view scene and copy into texture
6201 // (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)
6202 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6204 r_refdef.view = myview;
6205 if(r_water_scissormode.integer)
6207 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6208 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6209 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6212 r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
6214 r_refdef.view.clipplane = p->plane;
6215 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6216 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6218 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6220 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6221 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6222 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6223 R_RenderView_UpdateViewVectors();
6224 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6226 r_refdef.view.usecustompvs = true;
6227 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);
6231 PlaneClassify(&r_refdef.view.clipplane);
6233 R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6234 R_ClearScreen(r_refdef.fogenabled);
6235 if(r_water_scissormode.integer & 2)
6236 R_View_UpdateWithScissor(myscissor);
6239 R_AnimCache_CacheVisibleEntities();
6240 if(r_water_scissormode.integer & 1)
6241 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6242 R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6244 if (!p->fbo_refraction)
6245 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);
6246 r_fb.water.hideplayer = false;
6248 else if (p->materialflags & MATERIALFLAG_CAMERA)
6250 r_refdef.view = myview;
6252 r_refdef.view.clipplane = p->plane;
6253 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6254 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6256 r_refdef.view.width = r_fb.water.camerawidth;
6257 r_refdef.view.height = r_fb.water.cameraheight;
6258 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6259 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6260 r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6261 r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6263 if(p->camera_entity)
6265 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6266 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6269 // note: all of the view is used for displaying... so
6270 // there is no use in scissoring
6272 // reverse the cullface settings for this render
6273 r_refdef.view.cullface_front = GL_FRONT;
6274 r_refdef.view.cullface_back = GL_BACK;
6275 // also reverse the view matrix
6276 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
6277 R_RenderView_UpdateViewVectors();
6278 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6280 r_refdef.view.usecustompvs = true;
6281 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);
6284 // camera needs no clipplane
6285 r_refdef.view.useclipplane = false;
6287 PlaneClassify(&r_refdef.view.clipplane);
6289 r_fb.water.hideplayer = false;
6291 R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6292 R_ClearScreen(r_refdef.fogenabled);
6294 R_AnimCache_CacheVisibleEntities();
6295 R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6298 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);
6299 r_fb.water.hideplayer = false;
6303 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6304 r_fb.water.renderingscene = false;
6305 r_refdef.view = originalview;
6306 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6307 if (!r_fb.water.depthtexture)
6308 R_ClearScreen(r_refdef.fogenabled);
6310 R_AnimCache_CacheVisibleEntities();
6313 r_refdef.view = originalview;
6314 r_fb.water.renderingscene = false;
6315 Cvar_SetValueQuick(&r_water, 0);
6316 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
6318 // lowquality hack, restore cvars
6319 if (qualityreduction > 0)
6321 if (qualityreduction >= 1)
6323 Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6324 Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6325 Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6327 if (qualityreduction >= 2)
6329 Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6330 Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6331 Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6336 static void R_Bloom_StartFrame(void)
6339 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6340 int viewwidth, viewheight;
6341 qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6342 textype_t textype = TEXTYPE_COLORBUFFER;
6344 switch (vid.renderpath)
6346 case RENDERPATH_GL20:
6347 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6348 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6350 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6351 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6354 case RENDERPATH_GL11:
6355 case RENDERPATH_GL13:
6356 case RENDERPATH_GLES1:
6357 case RENDERPATH_GLES2:
6358 case RENDERPATH_D3D9:
6359 case RENDERPATH_D3D10:
6360 case RENDERPATH_D3D11:
6361 r_fb.usedepthtextures = false;
6363 case RENDERPATH_SOFT:
6364 r_fb.usedepthtextures = true;
6368 if (r_viewscale_fpsscaling.integer)
6370 double actualframetime;
6371 double targetframetime;
6373 actualframetime = r_refdef.lastdrawscreentime;
6374 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6375 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6376 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6377 if (r_viewscale_fpsscaling_stepsize.value > 0)
6378 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6379 viewscalefpsadjusted += adjust;
6380 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6383 viewscalefpsadjusted = 1.0f;
6385 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6387 switch(vid.renderpath)
6389 case RENDERPATH_GL20:
6390 case RENDERPATH_D3D9:
6391 case RENDERPATH_D3D10:
6392 case RENDERPATH_D3D11:
6393 case RENDERPATH_SOFT:
6394 case RENDERPATH_GLES2:
6396 case RENDERPATH_GL11:
6397 case RENDERPATH_GL13:
6398 case RENDERPATH_GLES1:
6402 // set bloomwidth and bloomheight to the bloom resolution that will be
6403 // used (often less than the screen resolution for faster rendering)
6404 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6405 r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6406 r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6407 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6408 r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6410 // calculate desired texture sizes
6411 if (vid.support.arb_texture_non_power_of_two)
6413 screentexturewidth = vid.width;
6414 screentextureheight = vid.height;
6415 bloomtexturewidth = r_fb.bloomwidth;
6416 bloomtextureheight = r_fb.bloomheight;
6420 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
6421 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
6422 for (bloomtexturewidth = 1;bloomtexturewidth < r_fb.bloomwidth ;bloomtexturewidth *= 2);
6423 for (bloomtextureheight = 1;bloomtextureheight < r_fb.bloomheight;bloomtextureheight *= 2);
6426 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))
6428 Cvar_SetValueQuick(&r_bloom, 0);
6429 Cvar_SetValueQuick(&r_motionblur, 0);
6430 Cvar_SetValueQuick(&r_damageblur, 0);
6433 if (!((r_glsl_postprocess.integer || r_fxaa.integer) || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6435 && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6437 && r_viewscale.value == 1.0f
6438 && !r_viewscale_fpsscaling.integer)
6439 screentexturewidth = screentextureheight = 0;
6440 if (!r_bloom.integer)
6441 bloomtexturewidth = bloomtextureheight = 0;
6443 // allocate textures as needed
6444 if (r_fb.screentexturewidth != screentexturewidth
6445 || r_fb.screentextureheight != screentextureheight
6446 || r_fb.bloomtexturewidth != bloomtexturewidth
6447 || r_fb.bloomtextureheight != bloomtextureheight
6448 || r_fb.textype != textype
6449 || useviewfbo != (r_fb.fbo != 0))
6451 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6453 if (r_fb.bloomtexture[i])
6454 R_FreeTexture(r_fb.bloomtexture[i]);
6455 r_fb.bloomtexture[i] = NULL;
6457 if (r_fb.bloomfbo[i])
6458 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6459 r_fb.bloomfbo[i] = 0;
6463 R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6466 if (r_fb.colortexture)
6467 R_FreeTexture(r_fb.colortexture);
6468 r_fb.colortexture = NULL;
6470 if (r_fb.depthtexture)
6471 R_FreeTexture(r_fb.depthtexture);
6472 r_fb.depthtexture = NULL;
6474 if (r_fb.ghosttexture)
6475 R_FreeTexture(r_fb.ghosttexture);
6476 r_fb.ghosttexture = NULL;
6478 r_fb.screentexturewidth = screentexturewidth;
6479 r_fb.screentextureheight = screentextureheight;
6480 r_fb.bloomtexturewidth = bloomtexturewidth;
6481 r_fb.bloomtextureheight = bloomtextureheight;
6482 r_fb.textype = textype;
6484 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6486 if (r_motionblur.value > 0 || r_damageblur.value > 0)
6487 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);
6488 r_fb.ghosttexture_valid = false;
6489 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);
6492 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6493 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6494 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6498 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6500 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6502 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);
6504 r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6509 // bloom texture is a different resolution
6510 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6511 r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6512 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6513 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6514 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6516 // set up a texcoord array for the full resolution screen image
6517 // (we have to keep this around to copy back during final render)
6518 r_fb.screentexcoord2f[0] = 0;
6519 r_fb.screentexcoord2f[1] = (float)viewheight / (float)r_fb.screentextureheight;
6520 r_fb.screentexcoord2f[2] = (float)viewwidth / (float)r_fb.screentexturewidth;
6521 r_fb.screentexcoord2f[3] = (float)viewheight / (float)r_fb.screentextureheight;
6522 r_fb.screentexcoord2f[4] = (float)viewwidth / (float)r_fb.screentexturewidth;
6523 r_fb.screentexcoord2f[5] = 0;
6524 r_fb.screentexcoord2f[6] = 0;
6525 r_fb.screentexcoord2f[7] = 0;
6529 for (i = 1;i < 8;i += 2)
6531 r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6535 // set up a texcoord array for the reduced resolution bloom image
6536 // (which will be additive blended over the screen image)
6537 r_fb.bloomtexcoord2f[0] = 0;
6538 r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6539 r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6540 r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6541 r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6542 r_fb.bloomtexcoord2f[5] = 0;
6543 r_fb.bloomtexcoord2f[6] = 0;
6544 r_fb.bloomtexcoord2f[7] = 0;
6546 switch(vid.renderpath)
6548 case RENDERPATH_GL11:
6549 case RENDERPATH_GL13:
6550 case RENDERPATH_GL20:
6551 case RENDERPATH_SOFT:
6552 case RENDERPATH_GLES1:
6553 case RENDERPATH_GLES2:
6555 case RENDERPATH_D3D9:
6556 case RENDERPATH_D3D10:
6557 case RENDERPATH_D3D11:
6558 for (i = 0;i < 4;i++)
6560 r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6561 r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6562 r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6563 r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6568 R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6571 r_refdef.view.clear = true;
6574 static void R_Bloom_MakeTexture(void)
6577 float xoffset, yoffset, r, brighten;
6579 float colorscale = r_bloom_colorscale.value;
6581 r_refdef.stats[r_stat_bloom]++;
6584 // this copy is unnecessary since it happens in R_BlendView already
6587 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);
6588 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6592 // scale down screen texture to the bloom texture size
6594 r_fb.bloomindex = 0;
6595 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6596 R_SetViewport(&r_fb.bloomviewport);
6597 GL_DepthTest(false);
6598 GL_BlendFunc(GL_ONE, GL_ZERO);
6599 GL_Color(colorscale, colorscale, colorscale, 1);
6600 // 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...
6601 switch(vid.renderpath)
6603 case RENDERPATH_GL11:
6604 case RENDERPATH_GL13:
6605 case RENDERPATH_GL20:
6606 case RENDERPATH_GLES1:
6607 case RENDERPATH_GLES2:
6608 case RENDERPATH_SOFT:
6609 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6611 case RENDERPATH_D3D9:
6612 case RENDERPATH_D3D10:
6613 case RENDERPATH_D3D11:
6614 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6617 // TODO: do boxfilter scale-down in shader?
6618 R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6619 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6620 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6622 // we now have a properly scaled bloom image
6623 if (!r_fb.bloomfbo[r_fb.bloomindex])
6625 // copy it into the bloom texture
6626 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);
6627 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6630 // multiply bloom image by itself as many times as desired
6631 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6633 intex = r_fb.bloomtexture[r_fb.bloomindex];
6634 r_fb.bloomindex ^= 1;
6635 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6637 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6638 if (!r_fb.bloomfbo[r_fb.bloomindex])
6640 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6641 GL_Color(r,r,r,1); // apply fix factor
6646 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6647 GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6648 GL_Color(1,1,1,1); // no fix factor supported here
6650 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6651 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6652 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6653 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6655 if (!r_fb.bloomfbo[r_fb.bloomindex])
6657 // copy the darkened image to a texture
6658 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);
6659 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6663 range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6664 brighten = r_bloom_brighten.value;
6665 brighten = sqrt(brighten);
6667 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6669 for (dir = 0;dir < 2;dir++)
6671 intex = r_fb.bloomtexture[r_fb.bloomindex];
6672 r_fb.bloomindex ^= 1;
6673 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6674 // blend on at multiple vertical offsets to achieve a vertical blur
6675 // TODO: do offset blends using GLSL
6676 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6677 GL_BlendFunc(GL_ONE, GL_ZERO);
6678 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6679 for (x = -range;x <= range;x++)
6681 if (!dir){xoffset = 0;yoffset = x;}
6682 else {xoffset = x;yoffset = 0;}
6683 xoffset /= (float)r_fb.bloomtexturewidth;
6684 yoffset /= (float)r_fb.bloomtextureheight;
6685 // compute a texcoord array with the specified x and y offset
6686 r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6687 r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6688 r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6689 r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6690 r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6691 r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6692 r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6693 r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6694 // this r value looks like a 'dot' particle, fading sharply to
6695 // black at the edges
6696 // (probably not realistic but looks good enough)
6697 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6698 //r = brighten/(range*2+1);
6699 r = brighten / (range * 2 + 1);
6701 r *= (1 - x*x/(float)(range*range));
6702 GL_Color(r, r, r, 1);
6703 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6704 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6705 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6706 GL_BlendFunc(GL_ONE, GL_ONE);
6709 if (!r_fb.bloomfbo[r_fb.bloomindex])
6711 // copy the vertically or horizontally blurred bloom view to a texture
6712 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);
6713 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6718 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6720 unsigned int permutation;
6721 float uservecs[4][4];
6723 R_EntityMatrix(&identitymatrix);
6725 switch (vid.renderpath)
6727 case RENDERPATH_GL20:
6728 case RENDERPATH_D3D9:
6729 case RENDERPATH_D3D10:
6730 case RENDERPATH_D3D11:
6731 case RENDERPATH_SOFT:
6732 case RENDERPATH_GLES2:
6734 (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6735 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6736 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6737 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6738 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6740 if (r_fb.colortexture)
6744 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);
6745 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6748 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6750 // declare variables
6751 float blur_factor, blur_mouseaccel, blur_velocity;
6752 static float blur_average;
6753 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6755 // set a goal for the factoring
6756 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value)
6757 / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6758 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value)
6759 / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6760 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value)
6761 + (blur_mouseaccel * r_motionblur_mousefactor.value));
6763 // from the goal, pick an averaged value between goal and last value
6764 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6765 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6767 // enforce minimum amount of blur
6768 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6770 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6772 // calculate values into a standard alpha
6773 cl.motionbluralpha = 1 - exp(-
6775 (r_motionblur.value * blur_factor / 80)
6777 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6780 max(0.0001, cl.time - cl.oldtime) // fps independent
6783 // randomization for the blur value to combat persistent ghosting
6784 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6785 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6788 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6789 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6791 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6792 GL_Color(1, 1, 1, cl.motionbluralpha);
6793 switch(vid.renderpath)
6795 case RENDERPATH_GL11:
6796 case RENDERPATH_GL13:
6797 case RENDERPATH_GL20:
6798 case RENDERPATH_GLES1:
6799 case RENDERPATH_GLES2:
6800 case RENDERPATH_SOFT:
6801 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6803 case RENDERPATH_D3D9:
6804 case RENDERPATH_D3D10:
6805 case RENDERPATH_D3D11:
6806 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6809 R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6810 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6811 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6814 // updates old view angles for next pass
6815 VectorCopy(cl.viewangles, blur_oldangles);
6817 // copy view into the ghost texture
6818 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);
6819 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6820 r_fb.ghosttexture_valid = true;
6825 // no r_fb.colortexture means we're rendering to the real fb
6826 // we may still have to do view tint...
6827 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6829 // apply a color tint to the whole view
6830 R_ResetViewRendering2D(0, NULL, NULL);
6831 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6832 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6833 R_SetupShader_Generic_NoTexture(false, true);
6834 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6835 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6837 break; // no screen processing, no bloom, skip it
6840 if (r_fb.bloomtexture[0])
6842 // make the bloom texture
6843 R_Bloom_MakeTexture();
6846 #if _MSC_VER >= 1400
6847 #define sscanf sscanf_s
6849 memset(uservecs, 0, sizeof(uservecs));
6850 if (r_glsl_postprocess_uservec1_enable.integer)
6851 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6852 if (r_glsl_postprocess_uservec2_enable.integer)
6853 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6854 if (r_glsl_postprocess_uservec3_enable.integer)
6855 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6856 if (r_glsl_postprocess_uservec4_enable.integer)
6857 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6859 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6860 GL_Color(1, 1, 1, 1);
6861 GL_BlendFunc(GL_ONE, GL_ZERO);
6863 switch(vid.renderpath)
6865 case RENDERPATH_GL20:
6866 case RENDERPATH_GLES2:
6867 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6868 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6869 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_fb.colortexture);
6870 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_fb.bloomtexture[r_fb.bloomindex]);
6871 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6872 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]);
6873 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6874 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]);
6875 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]);
6876 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]);
6877 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]);
6878 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6879 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6880 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);
6882 case RENDERPATH_D3D9:
6884 // 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...
6885 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6886 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6887 R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture);
6888 R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]);
6889 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6890 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6891 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6892 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6893 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6894 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6895 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6896 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6897 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6898 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6901 case RENDERPATH_D3D10:
6902 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6904 case RENDERPATH_D3D11:
6905 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6907 case RENDERPATH_SOFT:
6908 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6909 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6910 R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture);
6911 R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]);
6912 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6913 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6914 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6915 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6916 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6917 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6918 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6919 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6920 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6921 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6926 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6927 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6929 case RENDERPATH_GL11:
6930 case RENDERPATH_GL13:
6931 case RENDERPATH_GLES1:
6932 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6934 // apply a color tint to the whole view
6935 R_ResetViewRendering2D(0, NULL, NULL);
6936 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6937 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6938 R_SetupShader_Generic_NoTexture(false, true);
6939 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6940 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6946 matrix4x4_t r_waterscrollmatrix;
6948 void R_UpdateFog(void)
6951 if (gamemode == GAME_NEHAHRA)
6953 if (gl_fogenable.integer)
6955 r_refdef.oldgl_fogenable = true;
6956 r_refdef.fog_density = gl_fogdensity.value;
6957 r_refdef.fog_red = gl_fogred.value;
6958 r_refdef.fog_green = gl_foggreen.value;
6959 r_refdef.fog_blue = gl_fogblue.value;
6960 r_refdef.fog_alpha = 1;
6961 r_refdef.fog_start = 0;
6962 r_refdef.fog_end = gl_skyclip.value;
6963 r_refdef.fog_height = 1<<30;
6964 r_refdef.fog_fadedepth = 128;
6966 else if (r_refdef.oldgl_fogenable)
6968 r_refdef.oldgl_fogenable = false;
6969 r_refdef.fog_density = 0;
6970 r_refdef.fog_red = 0;
6971 r_refdef.fog_green = 0;
6972 r_refdef.fog_blue = 0;
6973 r_refdef.fog_alpha = 0;
6974 r_refdef.fog_start = 0;
6975 r_refdef.fog_end = 0;
6976 r_refdef.fog_height = 1<<30;
6977 r_refdef.fog_fadedepth = 128;
6982 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6983 r_refdef.fog_start = max(0, r_refdef.fog_start);
6984 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6986 if (r_refdef.fog_density && r_drawfog.integer)
6988 r_refdef.fogenabled = true;
6989 // this is the point where the fog reaches 0.9986 alpha, which we
6990 // consider a good enough cutoff point for the texture
6991 // (0.9986 * 256 == 255.6)
6992 if (r_fog_exp2.integer)
6993 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6995 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6996 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6997 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6998 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6999 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
7000 R_BuildFogHeightTexture();
7001 // fog color was already set
7002 // update the fog texture
7003 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)
7004 R_BuildFogTexture();
7005 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
7006 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
7009 r_refdef.fogenabled = false;
7012 if (r_refdef.fog_density)
7014 r_refdef.fogcolor[0] = r_refdef.fog_red;
7015 r_refdef.fogcolor[1] = r_refdef.fog_green;
7016 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7018 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7019 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7020 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7021 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7025 VectorCopy(r_refdef.fogcolor, fogvec);
7026 // color.rgb *= ContrastBoost * SceneBrightness;
7027 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7028 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7029 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7030 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7035 void R_UpdateVariables(void)
7039 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7041 r_refdef.farclip = r_farclip_base.value;
7042 if (r_refdef.scene.worldmodel)
7043 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7044 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7046 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7047 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7048 r_refdef.polygonfactor = 0;
7049 r_refdef.polygonoffset = 0;
7050 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7051 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7053 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7054 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7055 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
7056 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7057 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7058 if (FAKELIGHT_ENABLED)
7060 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
7062 else if (r_refdef.scene.worldmodel)
7064 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
7066 if (r_showsurfaces.integer)
7068 r_refdef.scene.rtworld = false;
7069 r_refdef.scene.rtworldshadows = false;
7070 r_refdef.scene.rtdlight = false;
7071 r_refdef.scene.rtdlightshadows = false;
7072 r_refdef.lightmapintensity = 0;
7075 r_gpuskeletal = false;
7076 switch(vid.renderpath)
7078 case RENDERPATH_GL20:
7079 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
7080 case RENDERPATH_D3D9:
7081 case RENDERPATH_D3D10:
7082 case RENDERPATH_D3D11:
7083 case RENDERPATH_SOFT:
7084 case RENDERPATH_GLES2:
7085 if(v_glslgamma.integer && !vid_gammatables_trivial)
7087 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7089 // build GLSL gamma texture
7090 #define RAMPWIDTH 256
7091 unsigned short ramp[RAMPWIDTH * 3];
7092 unsigned char rampbgr[RAMPWIDTH][4];
7095 r_texture_gammaramps_serial = vid_gammatables_serial;
7097 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7098 for(i = 0; i < RAMPWIDTH; ++i)
7100 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7101 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7102 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7105 if (r_texture_gammaramps)
7107 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7111 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7117 // remove GLSL gamma texture
7120 case RENDERPATH_GL11:
7121 case RENDERPATH_GL13:
7122 case RENDERPATH_GLES1:
7127 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7128 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7134 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7135 if( scenetype != r_currentscenetype ) {
7136 // store the old scenetype
7137 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7138 r_currentscenetype = scenetype;
7139 // move in the new scene
7140 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7149 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7151 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7152 if( scenetype == r_currentscenetype ) {
7153 return &r_refdef.scene;
7155 return &r_scenes_store[ scenetype ];
7159 static int R_SortEntities_Compare(const void *ap, const void *bp)
7161 const entity_render_t *a = *(const entity_render_t **)ap;
7162 const entity_render_t *b = *(const entity_render_t **)bp;
7165 if(a->model < b->model)
7167 if(a->model > b->model)
7171 // TODO possibly calculate the REAL skinnum here first using
7173 if(a->skinnum < b->skinnum)
7175 if(a->skinnum > b->skinnum)
7178 // everything we compared is equal
7181 static void R_SortEntities(void)
7183 // below or equal 2 ents, sorting never gains anything
7184 if(r_refdef.scene.numentities <= 2)
7187 qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7195 int dpsoftrast_test;
7196 extern cvar_t r_shadow_bouncegrid;
7197 void R_RenderView(void)
7199 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7201 rtexture_t *depthtexture;
7202 rtexture_t *colortexture;
7204 dpsoftrast_test = r_test.integer;
7206 if (r_timereport_active)
7207 R_TimeReport("start");
7208 r_textureframe++; // used only by R_GetCurrentTexture
7209 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7211 if(R_CompileShader_CheckStaticParms())
7214 if (!r_drawentities.integer)
7215 r_refdef.scene.numentities = 0;
7216 else if (r_sortentities.integer)
7219 R_AnimCache_ClearCache();
7221 /* adjust for stereo display */
7222 if(R_Stereo_Active())
7224 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);
7225 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7228 if (r_refdef.view.isoverlay)
7230 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7231 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7232 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7233 R_TimeReport("depthclear");
7235 r_refdef.view.showdebug = false;
7237 r_fb.water.enabled = false;
7238 r_fb.water.numwaterplanes = 0;
7240 R_RenderScene(0, NULL, NULL);
7242 r_refdef.view.matrix = originalmatrix;
7248 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7250 r_refdef.view.matrix = originalmatrix;
7254 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7256 if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7257 // in sRGB fallback, behave similar to true sRGB: convert this
7258 // value from linear to sRGB
7259 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7261 R_RenderView_UpdateViewVectors();
7263 R_Shadow_UpdateWorldLightSelection();
7265 R_Bloom_StartFrame();
7267 // apply bloom brightness offset
7268 if(r_fb.bloomtexture[0])
7269 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7271 R_Water_StartFrame();
7273 // now we probably have an fbo to render into
7275 depthtexture = r_fb.depthtexture;
7276 colortexture = r_fb.colortexture;
7279 if (r_timereport_active)
7280 R_TimeReport("viewsetup");
7282 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7284 if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7286 R_ClearScreen(r_refdef.fogenabled);
7287 if (r_timereport_active)
7288 R_TimeReport("viewclear");
7290 r_refdef.view.clear = true;
7292 r_refdef.view.showdebug = true;
7295 if (r_timereport_active)
7296 R_TimeReport("visibility");
7298 R_AnimCache_CacheVisibleEntities();
7299 if (r_timereport_active)
7300 R_TimeReport("animcache");
7302 R_Shadow_UpdateBounceGridTexture();
7303 if (r_timereport_active && r_shadow_bouncegrid.integer)
7304 R_TimeReport("bouncegrid");
7306 r_fb.water.numwaterplanes = 0;
7307 if (r_fb.water.enabled)
7308 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7310 R_RenderScene(fbo, depthtexture, colortexture);
7311 r_fb.water.numwaterplanes = 0;
7313 R_BlendView(fbo, depthtexture, colortexture);
7314 if (r_timereport_active)
7315 R_TimeReport("blendview");
7317 GL_Scissor(0, 0, vid.width, vid.height);
7318 GL_ScissorTest(false);
7320 r_refdef.view.matrix = originalmatrix;
7325 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7327 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7329 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7330 if (r_timereport_active)
7331 R_TimeReport("waterworld");
7334 // don't let sound skip if going slow
7335 if (r_refdef.scene.extraupdate)
7338 R_DrawModelsAddWaterPlanes();
7339 if (r_timereport_active)
7340 R_TimeReport("watermodels");
7342 if (r_fb.water.numwaterplanes)
7344 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7345 if (r_timereport_active)
7346 R_TimeReport("waterscenes");
7350 extern cvar_t cl_locs_show;
7351 static void R_DrawLocs(void);
7352 static void R_DrawEntityBBoxes(void);
7353 static void R_DrawModelDecals(void);
7354 extern cvar_t cl_decals_newsystem;
7355 extern qboolean r_shadow_usingdeferredprepass;
7356 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7358 qboolean shadowmapping = false;
7360 if (r_timereport_active)
7361 R_TimeReport("beginscene");
7363 r_refdef.stats[r_stat_renders]++;
7367 // don't let sound skip if going slow
7368 if (r_refdef.scene.extraupdate)
7371 R_MeshQueue_BeginScene();
7375 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);
7377 if (r_timereport_active)
7378 R_TimeReport("skystartframe");
7380 if (cl.csqc_vidvars.drawworld)
7382 // don't let sound skip if going slow
7383 if (r_refdef.scene.extraupdate)
7386 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7388 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7389 if (r_timereport_active)
7390 R_TimeReport("worldsky");
7393 if (R_DrawBrushModelsSky() && r_timereport_active)
7394 R_TimeReport("bmodelsky");
7396 if (skyrendermasked && skyrenderlater)
7398 // we have to force off the water clipping plane while rendering sky
7399 R_SetupView(false, fbo, depthtexture, colortexture);
7401 R_SetupView(true, fbo, depthtexture, colortexture);
7402 if (r_timereport_active)
7403 R_TimeReport("sky");
7407 R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7408 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7409 R_Shadow_PrepareModelShadows();
7410 if (r_timereport_active)
7411 R_TimeReport("preparelights");
7413 if (R_Shadow_ShadowMappingEnabled())
7414 shadowmapping = true;
7416 if (r_shadow_usingdeferredprepass)
7417 R_Shadow_DrawPrepass();
7419 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7421 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7422 if (r_timereport_active)
7423 R_TimeReport("worlddepth");
7425 if (r_depthfirst.integer >= 2)
7427 R_DrawModelsDepth();
7428 if (r_timereport_active)
7429 R_TimeReport("modeldepth");
7432 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7434 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7435 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7436 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7437 // don't let sound skip if going slow
7438 if (r_refdef.scene.extraupdate)
7442 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7444 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7445 if (r_timereport_active)
7446 R_TimeReport("world");
7449 // don't let sound skip if going slow
7450 if (r_refdef.scene.extraupdate)
7454 if (r_timereport_active)
7455 R_TimeReport("models");
7457 // don't let sound skip if going slow
7458 if (r_refdef.scene.extraupdate)
7461 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7463 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7464 R_DrawModelShadows(fbo, depthtexture, colortexture);
7465 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7466 // don't let sound skip if going slow
7467 if (r_refdef.scene.extraupdate)
7471 if (!r_shadow_usingdeferredprepass)
7473 R_Shadow_DrawLights();
7474 if (r_timereport_active)
7475 R_TimeReport("rtlights");
7478 // don't let sound skip if going slow
7479 if (r_refdef.scene.extraupdate)
7482 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7484 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7485 R_DrawModelShadows(fbo, depthtexture, colortexture);
7486 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7487 // don't let sound skip if going slow
7488 if (r_refdef.scene.extraupdate)
7492 if (cl.csqc_vidvars.drawworld)
7494 if (cl_decals_newsystem.integer)
7496 R_DrawModelDecals();
7497 if (r_timereport_active)
7498 R_TimeReport("modeldecals");
7503 if (r_timereport_active)
7504 R_TimeReport("decals");
7508 if (r_timereport_active)
7509 R_TimeReport("particles");
7512 if (r_timereport_active)
7513 R_TimeReport("explosions");
7515 R_DrawLightningBeams();
7516 if (r_timereport_active)
7517 R_TimeReport("lightning");
7521 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7523 if (r_refdef.view.showdebug)
7525 if (cl_locs_show.integer)
7528 if (r_timereport_active)
7529 R_TimeReport("showlocs");
7532 if (r_drawportals.integer)
7535 if (r_timereport_active)
7536 R_TimeReport("portals");
7539 if (r_showbboxes.value > 0)
7541 R_DrawEntityBBoxes();
7542 if (r_timereport_active)
7543 R_TimeReport("bboxes");
7547 if (r_transparent.integer)
7549 R_MeshQueue_RenderTransparent();
7550 if (r_timereport_active)
7551 R_TimeReport("drawtrans");
7554 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))
7556 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7557 if (r_timereport_active)
7558 R_TimeReport("worlddebug");
7559 R_DrawModelsDebug();
7560 if (r_timereport_active)
7561 R_TimeReport("modeldebug");
7564 if (cl.csqc_vidvars.drawworld)
7566 R_Shadow_DrawCoronas();
7567 if (r_timereport_active)
7568 R_TimeReport("coronas");
7573 GL_DepthTest(false);
7574 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7575 GL_Color(1, 1, 1, 1);
7576 qglBegin(GL_POLYGON);
7577 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7578 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7579 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7580 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7582 qglBegin(GL_POLYGON);
7583 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]);
7584 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]);
7585 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]);
7586 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]);
7588 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7592 // don't let sound skip if going slow
7593 if (r_refdef.scene.extraupdate)
7597 static const unsigned short bboxelements[36] =
7607 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7610 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7612 RSurf_ActiveWorldEntity();
7614 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7615 GL_DepthMask(false);
7616 GL_DepthRange(0, 1);
7617 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7618 // R_Mesh_ResetTextureState();
7620 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7621 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7622 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7623 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7624 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7625 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7626 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7627 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7628 R_FillColors(color4f, 8, cr, cg, cb, ca);
7629 if (r_refdef.fogenabled)
7631 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7633 f1 = RSurf_FogVertex(v);
7635 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7636 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7637 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7640 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7641 R_Mesh_ResetTextureState();
7642 R_SetupShader_Generic_NoTexture(false, false);
7643 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7646 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7648 prvm_prog_t *prog = SVVM_prog;
7651 prvm_edict_t *edict;
7653 // this function draws bounding boxes of server entities
7657 GL_CullFace(GL_NONE);
7658 R_SetupShader_Generic_NoTexture(false, false);
7660 for (i = 0;i < numsurfaces;i++)
7662 edict = PRVM_EDICT_NUM(surfacelist[i]);
7663 switch ((int)PRVM_serveredictfloat(edict, solid))
7665 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7666 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7667 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7668 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7669 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7670 case SOLID_CORPSE: Vector4Set(color, 1, 0.5, 0, 0.05);break;
7671 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7673 color[3] *= r_showbboxes.value;
7674 color[3] = bound(0, color[3], 1);
7675 GL_DepthTest(!r_showdisabledepthtest.integer);
7676 GL_CullFace(r_refdef.view.cullface_front);
7677 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7681 static void R_DrawEntityBBoxes(void)
7684 prvm_edict_t *edict;
7686 prvm_prog_t *prog = SVVM_prog;
7688 // this function draws bounding boxes of server entities
7692 for (i = 0;i < prog->num_edicts;i++)
7694 edict = PRVM_EDICT_NUM(i);
7695 if (edict->priv.server->free)
7697 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7698 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7700 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7702 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7703 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7707 static const int nomodelelement3i[24] =
7719 static const unsigned short nomodelelement3s[24] =
7731 static const float nomodelvertex3f[6*3] =
7741 static const float nomodelcolor4f[6*4] =
7743 0.0f, 0.0f, 0.5f, 1.0f,
7744 0.0f, 0.0f, 0.5f, 1.0f,
7745 0.0f, 0.5f, 0.0f, 1.0f,
7746 0.0f, 0.5f, 0.0f, 1.0f,
7747 0.5f, 0.0f, 0.0f, 1.0f,
7748 0.5f, 0.0f, 0.0f, 1.0f
7751 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7757 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);
7759 // this is only called once per entity so numsurfaces is always 1, and
7760 // surfacelist is always {0}, so this code does not handle batches
7762 if (rsurface.ent_flags & RENDER_ADDITIVE)
7764 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7765 GL_DepthMask(false);
7767 else if (rsurface.colormod[3] < 1)
7769 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7770 GL_DepthMask(false);
7774 GL_BlendFunc(GL_ONE, GL_ZERO);
7777 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7778 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7779 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7780 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7781 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7782 for (i = 0, c = color4f;i < 6;i++, c += 4)
7784 c[0] *= rsurface.colormod[0];
7785 c[1] *= rsurface.colormod[1];
7786 c[2] *= rsurface.colormod[2];
7787 c[3] *= rsurface.colormod[3];
7789 if (r_refdef.fogenabled)
7791 for (i = 0, c = color4f;i < 6;i++, c += 4)
7793 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7795 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7796 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7797 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7800 // R_Mesh_ResetTextureState();
7801 R_SetupShader_Generic_NoTexture(false, false);
7802 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7803 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7806 void R_DrawNoModel(entity_render_t *ent)
7809 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7810 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7811 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7813 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7816 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7818 vec3_t right1, right2, diff, normal;
7820 VectorSubtract (org2, org1, normal);
7822 // calculate 'right' vector for start
7823 VectorSubtract (r_refdef.view.origin, org1, diff);
7824 CrossProduct (normal, diff, right1);
7825 VectorNormalize (right1);
7827 // calculate 'right' vector for end
7828 VectorSubtract (r_refdef.view.origin, org2, diff);
7829 CrossProduct (normal, diff, right2);
7830 VectorNormalize (right2);
7832 vert[ 0] = org1[0] + width * right1[0];
7833 vert[ 1] = org1[1] + width * right1[1];
7834 vert[ 2] = org1[2] + width * right1[2];
7835 vert[ 3] = org1[0] - width * right1[0];
7836 vert[ 4] = org1[1] - width * right1[1];
7837 vert[ 5] = org1[2] - width * right1[2];
7838 vert[ 6] = org2[0] - width * right2[0];
7839 vert[ 7] = org2[1] - width * right2[1];
7840 vert[ 8] = org2[2] - width * right2[2];
7841 vert[ 9] = org2[0] + width * right2[0];
7842 vert[10] = org2[1] + width * right2[1];
7843 vert[11] = org2[2] + width * right2[2];
7846 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)
7848 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7849 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7850 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7851 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7852 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7853 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7854 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7855 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7856 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7857 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7858 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7859 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7862 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7867 VectorSet(v, x, y, z);
7868 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7869 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7871 if (i == mesh->numvertices)
7873 if (mesh->numvertices < mesh->maxvertices)
7875 VectorCopy(v, vertex3f);
7876 mesh->numvertices++;
7878 return mesh->numvertices;
7884 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7888 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7889 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7890 e = mesh->element3i + mesh->numtriangles * 3;
7891 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7893 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7894 if (mesh->numtriangles < mesh->maxtriangles)
7899 mesh->numtriangles++;
7901 element[1] = element[2];
7905 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7909 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7910 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7911 e = mesh->element3i + mesh->numtriangles * 3;
7912 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7914 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7915 if (mesh->numtriangles < mesh->maxtriangles)
7920 mesh->numtriangles++;
7922 element[1] = element[2];
7926 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7927 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7929 int planenum, planenum2;
7932 mplane_t *plane, *plane2;
7934 double temppoints[2][256*3];
7935 // figure out how large a bounding box we need to properly compute this brush
7937 for (w = 0;w < numplanes;w++)
7938 maxdist = max(maxdist, fabs(planes[w].dist));
7939 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7940 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7941 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7945 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7946 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7948 if (planenum2 == planenum)
7950 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);
7953 if (tempnumpoints < 3)
7955 // generate elements forming a triangle fan for this polygon
7956 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7960 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)
7962 texturelayer_t *layer;
7963 layer = t->currentlayers + t->currentnumlayers++;
7965 layer->depthmask = depthmask;
7966 layer->blendfunc1 = blendfunc1;
7967 layer->blendfunc2 = blendfunc2;
7968 layer->texture = texture;
7969 layer->texmatrix = *matrix;
7970 layer->color[0] = r;
7971 layer->color[1] = g;
7972 layer->color[2] = b;
7973 layer->color[3] = a;
7976 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7978 if(parms[0] == 0 && parms[1] == 0)
7980 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7981 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7986 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7989 index = parms[2] + rsurface.shadertime * parms[3];
7990 index -= floor(index);
7991 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7994 case Q3WAVEFUNC_NONE:
7995 case Q3WAVEFUNC_NOISE:
7996 case Q3WAVEFUNC_COUNT:
7999 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8000 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8001 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8002 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8003 case Q3WAVEFUNC_TRIANGLE:
8005 f = index - floor(index);
8018 f = parms[0] + parms[1] * f;
8019 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8020 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
8024 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8031 matrix4x4_t matrix, temp;
8032 // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
8033 // it's better to have one huge fixup every 9 hours than gradual
8034 // degradation over time which looks consistently bad after many hours.
8036 // tcmod scroll in particular suffers from this degradation which can't be
8037 // effectively worked around even with floor() tricks because we don't
8038 // know if tcmod scroll is the last tcmod being applied, and for clampmap
8039 // a workaround involving floor() would be incorrect anyway...
8040 shadertime = rsurface.shadertime;
8041 if (shadertime >= 32768.0f)
8042 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
8043 switch(tcmod->tcmod)
8047 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8048 matrix = r_waterscrollmatrix;
8050 matrix = identitymatrix;
8052 case Q3TCMOD_ENTITYTRANSLATE:
8053 // this is used in Q3 to allow the gamecode to control texcoord
8054 // scrolling on the entity, which is not supported in darkplaces yet.
8055 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8057 case Q3TCMOD_ROTATE:
8058 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8059 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
8060 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8063 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8065 case Q3TCMOD_SCROLL:
8066 // this particular tcmod is a "bug for bug" compatible one with regards to
8067 // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
8068 // specifically did the wrapping and so we must mimic that...
8069 offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
8070 offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
8071 Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
8073 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8074 w = (int) tcmod->parms[0];
8075 h = (int) tcmod->parms[1];
8076 f = rsurface.shadertime / (tcmod->parms[2] * w * h);
8078 idx = (int) floor(f * w * h);
8079 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8081 case Q3TCMOD_STRETCH:
8082 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8083 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8085 case Q3TCMOD_TRANSFORM:
8086 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
8087 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
8088 VectorSet(tcmat + 6, 0 , 0 , 1);
8089 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
8090 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8092 case Q3TCMOD_TURBULENT:
8093 // this is handled in the RSurf_PrepareVertices function
8094 matrix = identitymatrix;
8098 Matrix4x4_Concat(texmatrix, &matrix, &temp);
8101 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8103 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8104 char name[MAX_QPATH];
8105 skinframe_t *skinframe;
8106 unsigned char pixels[296*194];
8107 strlcpy(cache->name, skinname, sizeof(cache->name));
8108 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8109 if (developer_loading.integer)
8110 Con_Printf("loading %s\n", name);
8111 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8112 if (!skinframe || !skinframe->base)
8115 fs_offset_t filesize;
8117 f = FS_LoadFile(name, tempmempool, true, &filesize);
8120 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8121 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8125 cache->skinframe = skinframe;
8128 texture_t *R_GetCurrentTexture(texture_t *t)
8131 const entity_render_t *ent = rsurface.entity;
8132 dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8133 q3shaderinfo_layer_tcmod_t *tcmod;
8135 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8136 return t->currentframe;
8137 t->update_lastrenderframe = r_textureframe;
8138 t->update_lastrenderentity = (void *)ent;
8140 if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8141 t->camera_entity = ent->entitynumber;
8143 t->camera_entity = 0;
8145 // switch to an alternate material if this is a q1bsp animated material
8147 texture_t *texture = t;
8148 int s = rsurface.ent_skinnum;
8149 if ((unsigned int)s >= (unsigned int)model->numskins)
8151 if (model->skinscenes)
8153 if (model->skinscenes[s].framecount > 1)
8154 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8156 s = model->skinscenes[s].firstframe;
8159 t = t + s * model->num_surfaces;
8162 // use an alternate animation if the entity's frame is not 0,
8163 // and only if the texture has an alternate animation
8164 if (t->animated == 2) // q2bsp
8165 t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]];
8166 else if (rsurface.ent_alttextures && t->anim_total[1])
8167 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8169 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8171 texture->currentframe = t;
8174 // update currentskinframe to be a qw skin or animation frame
8175 if (rsurface.ent_qwskin >= 0)
8177 i = rsurface.ent_qwskin;
8178 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8180 r_qwskincache_size = cl.maxclients;
8182 Mem_Free(r_qwskincache);
8183 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8185 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8186 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8187 t->currentskinframe = r_qwskincache[i].skinframe;
8188 if (t->currentskinframe == NULL)
8189 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8191 else if (t->numskinframes >= 2)
8192 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8193 if (t->backgroundnumskinframes >= 2)
8194 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
8196 t->currentmaterialflags = t->basematerialflags;
8197 t->currentalpha = rsurface.colormod[3] * t->basealpha;
8198 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8199 t->currentalpha *= r_wateralpha.value;
8200 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8201 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8202 if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8203 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8204 if (!(rsurface.ent_flags & RENDER_LIGHT))
8205 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8206 else if (FAKELIGHT_ENABLED)
8208 // no modellight if using fakelight for the map
8210 else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8212 // pick a model lighting mode
8213 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8214 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8216 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8218 if (rsurface.ent_flags & RENDER_ADDITIVE)
8219 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8220 else if (t->currentalpha < 1)
8221 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8222 // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8223 if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8224 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8225 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8226 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8227 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8228 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8229 if (t->backgroundnumskinframes)
8230 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8231 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8233 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8234 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8237 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8238 if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8240 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8241 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8243 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8244 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8246 // there is no tcmod
8247 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8249 t->currenttexmatrix = r_waterscrollmatrix;
8250 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8252 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8254 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8255 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8258 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8259 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8260 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8261 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8263 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8264 if (t->currentskinframe->qpixels)
8265 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8266 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8267 if (!t->basetexture)
8268 t->basetexture = r_texture_notexture;
8269 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8270 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8271 t->nmaptexture = t->currentskinframe->nmap;
8272 if (!t->nmaptexture)
8273 t->nmaptexture = r_texture_blanknormalmap;
8274 t->glosstexture = r_texture_black;
8275 t->glowtexture = t->currentskinframe->glow;
8276 t->fogtexture = t->currentskinframe->fog;
8277 t->reflectmasktexture = t->currentskinframe->reflect;
8278 if (t->backgroundnumskinframes)
8280 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8281 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8282 t->backgroundglosstexture = r_texture_black;
8283 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8284 if (!t->backgroundnmaptexture)
8285 t->backgroundnmaptexture = r_texture_blanknormalmap;
8286 // make sure that if glow is going to be used, both textures are not NULL
8287 if (!t->backgroundglowtexture && t->glowtexture)
8288 t->backgroundglowtexture = r_texture_black;
8289 if (!t->glowtexture && t->backgroundglowtexture)
8290 t->glowtexture = r_texture_black;
8294 t->backgroundbasetexture = r_texture_white;
8295 t->backgroundnmaptexture = r_texture_blanknormalmap;
8296 t->backgroundglosstexture = r_texture_black;
8297 t->backgroundglowtexture = NULL;
8299 t->specularpower = r_shadow_glossexponent.value;
8300 // TODO: store reference values for these in the texture?
8301 t->specularscale = 0;
8302 if (r_shadow_gloss.integer > 0)
8304 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8306 if (r_shadow_glossintensity.value > 0)
8308 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8309 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8310 t->specularscale = r_shadow_glossintensity.value;
8313 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8315 t->glosstexture = r_texture_white;
8316 t->backgroundglosstexture = r_texture_white;
8317 t->specularscale = r_shadow_gloss2intensity.value;
8318 t->specularpower = r_shadow_gloss2exponent.value;
8321 t->specularscale *= t->specularscalemod;
8322 t->specularpower *= t->specularpowermod;
8323 t->rtlightambient = 0;
8325 // lightmaps mode looks bad with dlights using actual texturing, so turn
8326 // off the colormap and glossmap, but leave the normalmap on as it still
8327 // accurately represents the shading involved
8328 if (gl_lightmaps.integer)
8330 t->basetexture = r_texture_grey128;
8331 t->pantstexture = r_texture_black;
8332 t->shirttexture = r_texture_black;
8333 if (gl_lightmaps.integer < 2)
8334 t->nmaptexture = r_texture_blanknormalmap;
8335 t->glosstexture = r_texture_black;
8336 t->glowtexture = NULL;
8337 t->fogtexture = NULL;
8338 t->reflectmasktexture = NULL;
8339 t->backgroundbasetexture = NULL;
8340 if (gl_lightmaps.integer < 2)
8341 t->backgroundnmaptexture = r_texture_blanknormalmap;
8342 t->backgroundglosstexture = r_texture_black;
8343 t->backgroundglowtexture = NULL;
8344 t->specularscale = 0;
8345 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8348 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8349 VectorClear(t->dlightcolor);
8350 t->currentnumlayers = 0;
8351 if (t->currentmaterialflags & MATERIALFLAG_WALL)
8353 int blendfunc1, blendfunc2;
8355 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8357 blendfunc1 = GL_SRC_ALPHA;
8358 blendfunc2 = GL_ONE;
8360 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8362 blendfunc1 = GL_SRC_ALPHA;
8363 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8365 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8367 blendfunc1 = t->customblendfunc[0];
8368 blendfunc2 = t->customblendfunc[1];
8372 blendfunc1 = GL_ONE;
8373 blendfunc2 = GL_ZERO;
8375 // don't colormod evilblend textures
8376 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8377 VectorSet(t->lightmapcolor, 1, 1, 1);
8378 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8379 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8381 // fullbright is not affected by r_refdef.lightmapintensity
8382 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]);
8383 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8384 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]);
8385 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8386 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]);
8390 vec3_t ambientcolor;
8392 // set the color tint used for lights affecting this surface
8393 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8395 // q3bsp has no lightmap updates, so the lightstylevalue that
8396 // would normally be baked into the lightmap must be
8397 // applied to the color
8398 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8399 if (model->type == mod_brushq3)
8400 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8401 colorscale *= r_refdef.lightmapintensity;
8402 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8403 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8404 // basic lit geometry
8405 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]);
8406 // add pants/shirt if needed
8407 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8408 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]);
8409 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8410 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]);
8411 // now add ambient passes if needed
8412 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8414 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]);
8415 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8416 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]);
8417 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8418 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]);
8421 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8422 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]);
8423 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8425 // if this is opaque use alpha blend which will darken the earlier
8428 // if this is an alpha blended material, all the earlier passes
8429 // were darkened by fog already, so we only need to add the fog
8430 // color ontop through the fog mask texture
8432 // if this is an additive blended material, all the earlier passes
8433 // were darkened by fog already, and we should not add fog color
8434 // (because the background was not darkened, there is no fog color
8435 // that was lost behind it).
8436 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]);
8443 rsurfacestate_t rsurface;
8445 void RSurf_ActiveWorldEntity(void)
8447 dp_model_t *model = r_refdef.scene.worldmodel;
8448 //if (rsurface.entity == r_refdef.scene.worldentity)
8450 rsurface.entity = r_refdef.scene.worldentity;
8451 rsurface.skeleton = NULL;
8452 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8453 rsurface.ent_skinnum = 0;
8454 rsurface.ent_qwskin = -1;
8455 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8456 rsurface.shadertime = r_refdef.scene.time;
8457 rsurface.matrix = identitymatrix;
8458 rsurface.inversematrix = identitymatrix;
8459 rsurface.matrixscale = 1;
8460 rsurface.inversematrixscale = 1;
8461 R_EntityMatrix(&identitymatrix);
8462 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8463 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8464 rsurface.fograngerecip = r_refdef.fograngerecip;
8465 rsurface.fogheightfade = r_refdef.fogheightfade;
8466 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8467 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8468 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8469 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8470 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8471 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8472 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8473 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8474 rsurface.colormod[3] = 1;
8475 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);
8476 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8477 rsurface.frameblend[0].lerp = 1;
8478 rsurface.ent_alttextures = false;
8479 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8480 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8481 rsurface.entityskeletaltransform3x4 = NULL;
8482 rsurface.entityskeletaltransform3x4buffer = NULL;
8483 rsurface.entityskeletaltransform3x4offset = 0;
8484 rsurface.entityskeletaltransform3x4size = 0;;
8485 rsurface.entityskeletalnumtransforms = 0;
8486 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8487 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8488 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8489 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8490 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8491 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8492 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8493 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8494 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8495 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8496 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8497 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8498 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8499 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8500 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8501 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8502 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8503 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8504 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8505 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8506 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8507 rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8508 rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8509 rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8510 rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8511 rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8512 rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8513 rsurface.modelelement3i = model->surfmesh.data_element3i;
8514 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8515 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8516 rsurface.modelelement3s = model->surfmesh.data_element3s;
8517 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8518 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8519 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8520 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8521 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8522 rsurface.modelsurfaces = model->data_surfaces;
8523 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8524 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8525 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8526 rsurface.modelgeneratedvertex = false;
8527 rsurface.batchgeneratedvertex = false;
8528 rsurface.batchfirstvertex = 0;
8529 rsurface.batchnumvertices = 0;
8530 rsurface.batchfirsttriangle = 0;
8531 rsurface.batchnumtriangles = 0;
8532 rsurface.batchvertex3f = NULL;
8533 rsurface.batchvertex3f_vertexbuffer = NULL;
8534 rsurface.batchvertex3f_bufferoffset = 0;
8535 rsurface.batchsvector3f = NULL;
8536 rsurface.batchsvector3f_vertexbuffer = NULL;
8537 rsurface.batchsvector3f_bufferoffset = 0;
8538 rsurface.batchtvector3f = NULL;
8539 rsurface.batchtvector3f_vertexbuffer = NULL;
8540 rsurface.batchtvector3f_bufferoffset = 0;
8541 rsurface.batchnormal3f = NULL;
8542 rsurface.batchnormal3f_vertexbuffer = NULL;
8543 rsurface.batchnormal3f_bufferoffset = 0;
8544 rsurface.batchlightmapcolor4f = NULL;
8545 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8546 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8547 rsurface.batchtexcoordtexture2f = NULL;
8548 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8549 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8550 rsurface.batchtexcoordlightmap2f = NULL;
8551 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8552 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8553 rsurface.batchskeletalindex4ub = NULL;
8554 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8555 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8556 rsurface.batchskeletalweight4ub = NULL;
8557 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8558 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8559 rsurface.batchvertexmesh = NULL;
8560 rsurface.batchvertexmesh_vertexbuffer = NULL;
8561 rsurface.batchvertexmesh_bufferoffset = 0;
8562 rsurface.batchelement3i = NULL;
8563 rsurface.batchelement3i_indexbuffer = NULL;
8564 rsurface.batchelement3i_bufferoffset = 0;
8565 rsurface.batchelement3s = NULL;
8566 rsurface.batchelement3s_indexbuffer = NULL;
8567 rsurface.batchelement3s_bufferoffset = 0;
8568 rsurface.passcolor4f = NULL;
8569 rsurface.passcolor4f_vertexbuffer = NULL;
8570 rsurface.passcolor4f_bufferoffset = 0;
8571 rsurface.forcecurrenttextureupdate = false;
8574 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8576 dp_model_t *model = ent->model;
8577 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8579 rsurface.entity = (entity_render_t *)ent;
8580 rsurface.skeleton = ent->skeleton;
8581 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8582 rsurface.ent_skinnum = ent->skinnum;
8583 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;
8584 rsurface.ent_flags = ent->flags;
8585 rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8586 rsurface.matrix = ent->matrix;
8587 rsurface.inversematrix = ent->inversematrix;
8588 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8589 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8590 R_EntityMatrix(&rsurface.matrix);
8591 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8592 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8593 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8594 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8595 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8596 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8597 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8598 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8599 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8600 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8601 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8602 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8603 rsurface.colormod[3] = ent->alpha;
8604 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8605 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8606 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8607 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8608 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8609 if (ent->model->brush.submodel && !prepass)
8611 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8612 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8614 // if the animcache code decided it should use the shader path, skip the deform step
8615 rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8616 rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8617 rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8618 rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8619 rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8620 if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8622 if (ent->animcache_vertex3f)
8624 r_refdef.stats[r_stat_batch_entitycache_count]++;
8625 r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8626 r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8627 r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8628 rsurface.modelvertex3f = ent->animcache_vertex3f;
8629 rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8630 rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8631 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8632 rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8633 rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8634 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8635 rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8636 rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8637 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8638 rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8639 rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8640 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8641 rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8642 rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8644 else if (wanttangents)
8646 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8647 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8648 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8649 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8650 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8651 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8652 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8653 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8654 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8655 rsurface.modelvertexmesh = NULL;
8656 rsurface.modelvertexmesh_vertexbuffer = NULL;
8657 rsurface.modelvertexmesh_bufferoffset = 0;
8658 rsurface.modelvertex3f_vertexbuffer = NULL;
8659 rsurface.modelvertex3f_bufferoffset = 0;
8660 rsurface.modelvertex3f_vertexbuffer = 0;
8661 rsurface.modelvertex3f_bufferoffset = 0;
8662 rsurface.modelsvector3f_vertexbuffer = 0;
8663 rsurface.modelsvector3f_bufferoffset = 0;
8664 rsurface.modeltvector3f_vertexbuffer = 0;
8665 rsurface.modeltvector3f_bufferoffset = 0;
8666 rsurface.modelnormal3f_vertexbuffer = 0;
8667 rsurface.modelnormal3f_bufferoffset = 0;
8669 else if (wantnormals)
8671 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8672 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8673 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8674 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8675 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8676 rsurface.modelsvector3f = NULL;
8677 rsurface.modeltvector3f = NULL;
8678 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8679 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8680 rsurface.modelvertexmesh = NULL;
8681 rsurface.modelvertexmesh_vertexbuffer = NULL;
8682 rsurface.modelvertexmesh_bufferoffset = 0;
8683 rsurface.modelvertex3f_vertexbuffer = NULL;
8684 rsurface.modelvertex3f_bufferoffset = 0;
8685 rsurface.modelvertex3f_vertexbuffer = 0;
8686 rsurface.modelvertex3f_bufferoffset = 0;
8687 rsurface.modelsvector3f_vertexbuffer = 0;
8688 rsurface.modelsvector3f_bufferoffset = 0;
8689 rsurface.modeltvector3f_vertexbuffer = 0;
8690 rsurface.modeltvector3f_bufferoffset = 0;
8691 rsurface.modelnormal3f_vertexbuffer = 0;
8692 rsurface.modelnormal3f_bufferoffset = 0;
8696 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8697 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8698 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8699 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8700 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8701 rsurface.modelsvector3f = NULL;
8702 rsurface.modeltvector3f = NULL;
8703 rsurface.modelnormal3f = NULL;
8704 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8705 rsurface.modelvertexmesh = NULL;
8706 rsurface.modelvertexmesh_vertexbuffer = NULL;
8707 rsurface.modelvertexmesh_bufferoffset = 0;
8708 rsurface.modelvertex3f_vertexbuffer = NULL;
8709 rsurface.modelvertex3f_bufferoffset = 0;
8710 rsurface.modelvertex3f_vertexbuffer = 0;
8711 rsurface.modelvertex3f_bufferoffset = 0;
8712 rsurface.modelsvector3f_vertexbuffer = 0;
8713 rsurface.modelsvector3f_bufferoffset = 0;
8714 rsurface.modeltvector3f_vertexbuffer = 0;
8715 rsurface.modeltvector3f_bufferoffset = 0;
8716 rsurface.modelnormal3f_vertexbuffer = 0;
8717 rsurface.modelnormal3f_bufferoffset = 0;
8719 rsurface.modelgeneratedvertex = true;
8723 if (rsurface.entityskeletaltransform3x4)
8725 r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8726 r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8727 r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8728 r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8732 r_refdef.stats[r_stat_batch_entitystatic_count]++;
8733 r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8734 r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8735 r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8737 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8738 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8739 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8740 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8741 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8742 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8743 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8744 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8745 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8746 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8747 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8748 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8749 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8750 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8751 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8752 rsurface.modelgeneratedvertex = false;
8754 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8755 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8756 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8757 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8758 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8759 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8760 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8761 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8762 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8763 rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8764 rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8765 rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8766 rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8767 rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8768 rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8769 rsurface.modelelement3i = model->surfmesh.data_element3i;
8770 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8771 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8772 rsurface.modelelement3s = model->surfmesh.data_element3s;
8773 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8774 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8775 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8776 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8777 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8778 rsurface.modelsurfaces = model->data_surfaces;
8779 rsurface.batchgeneratedvertex = false;
8780 rsurface.batchfirstvertex = 0;
8781 rsurface.batchnumvertices = 0;
8782 rsurface.batchfirsttriangle = 0;
8783 rsurface.batchnumtriangles = 0;
8784 rsurface.batchvertex3f = NULL;
8785 rsurface.batchvertex3f_vertexbuffer = NULL;
8786 rsurface.batchvertex3f_bufferoffset = 0;
8787 rsurface.batchsvector3f = NULL;
8788 rsurface.batchsvector3f_vertexbuffer = NULL;
8789 rsurface.batchsvector3f_bufferoffset = 0;
8790 rsurface.batchtvector3f = NULL;
8791 rsurface.batchtvector3f_vertexbuffer = NULL;
8792 rsurface.batchtvector3f_bufferoffset = 0;
8793 rsurface.batchnormal3f = NULL;
8794 rsurface.batchnormal3f_vertexbuffer = NULL;
8795 rsurface.batchnormal3f_bufferoffset = 0;
8796 rsurface.batchlightmapcolor4f = NULL;
8797 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8798 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8799 rsurface.batchtexcoordtexture2f = NULL;
8800 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8801 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8802 rsurface.batchtexcoordlightmap2f = NULL;
8803 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8804 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8805 rsurface.batchskeletalindex4ub = NULL;
8806 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8807 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8808 rsurface.batchskeletalweight4ub = NULL;
8809 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8810 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8811 rsurface.batchvertexmesh = NULL;
8812 rsurface.batchvertexmesh_vertexbuffer = NULL;
8813 rsurface.batchvertexmesh_bufferoffset = 0;
8814 rsurface.batchelement3i = NULL;
8815 rsurface.batchelement3i_indexbuffer = NULL;
8816 rsurface.batchelement3i_bufferoffset = 0;
8817 rsurface.batchelement3s = NULL;
8818 rsurface.batchelement3s_indexbuffer = NULL;
8819 rsurface.batchelement3s_bufferoffset = 0;
8820 rsurface.passcolor4f = NULL;
8821 rsurface.passcolor4f_vertexbuffer = NULL;
8822 rsurface.passcolor4f_bufferoffset = 0;
8823 rsurface.forcecurrenttextureupdate = false;
8826 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)
8828 rsurface.entity = r_refdef.scene.worldentity;
8829 rsurface.skeleton = NULL;
8830 rsurface.ent_skinnum = 0;
8831 rsurface.ent_qwskin = -1;
8832 rsurface.ent_flags = entflags;
8833 rsurface.shadertime = r_refdef.scene.time - shadertime;
8834 rsurface.modelnumvertices = numvertices;
8835 rsurface.modelnumtriangles = numtriangles;
8836 rsurface.matrix = *matrix;
8837 rsurface.inversematrix = *inversematrix;
8838 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8839 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8840 R_EntityMatrix(&rsurface.matrix);
8841 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8842 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8843 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8844 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8845 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8846 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8847 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8848 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8849 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8850 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8851 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8852 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8853 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);
8854 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8855 rsurface.frameblend[0].lerp = 1;
8856 rsurface.ent_alttextures = false;
8857 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8858 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8859 rsurface.entityskeletaltransform3x4 = NULL;
8860 rsurface.entityskeletaltransform3x4buffer = NULL;
8861 rsurface.entityskeletaltransform3x4offset = 0;
8862 rsurface.entityskeletaltransform3x4size = 0;
8863 rsurface.entityskeletalnumtransforms = 0;
8864 r_refdef.stats[r_stat_batch_entitycustom_count]++;
8865 r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8866 r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8867 r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8870 rsurface.modelvertex3f = (float *)vertex3f;
8871 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8872 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8873 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8875 else if (wantnormals)
8877 rsurface.modelvertex3f = (float *)vertex3f;
8878 rsurface.modelsvector3f = NULL;
8879 rsurface.modeltvector3f = NULL;
8880 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8884 rsurface.modelvertex3f = (float *)vertex3f;
8885 rsurface.modelsvector3f = NULL;
8886 rsurface.modeltvector3f = NULL;
8887 rsurface.modelnormal3f = NULL;
8889 rsurface.modelvertexmesh = NULL;
8890 rsurface.modelvertexmesh_vertexbuffer = NULL;
8891 rsurface.modelvertexmesh_bufferoffset = 0;
8892 rsurface.modelvertex3f_vertexbuffer = 0;
8893 rsurface.modelvertex3f_bufferoffset = 0;
8894 rsurface.modelsvector3f_vertexbuffer = 0;
8895 rsurface.modelsvector3f_bufferoffset = 0;
8896 rsurface.modeltvector3f_vertexbuffer = 0;
8897 rsurface.modeltvector3f_bufferoffset = 0;
8898 rsurface.modelnormal3f_vertexbuffer = 0;
8899 rsurface.modelnormal3f_bufferoffset = 0;
8900 rsurface.modelgeneratedvertex = true;
8901 rsurface.modellightmapcolor4f = (float *)color4f;
8902 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8903 rsurface.modellightmapcolor4f_bufferoffset = 0;
8904 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8905 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8906 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8907 rsurface.modeltexcoordlightmap2f = NULL;
8908 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8909 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8910 rsurface.modelskeletalindex4ub = NULL;
8911 rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8912 rsurface.modelskeletalindex4ub_bufferoffset = 0;
8913 rsurface.modelskeletalweight4ub = NULL;
8914 rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8915 rsurface.modelskeletalweight4ub_bufferoffset = 0;
8916 rsurface.modelelement3i = (int *)element3i;
8917 rsurface.modelelement3i_indexbuffer = NULL;
8918 rsurface.modelelement3i_bufferoffset = 0;
8919 rsurface.modelelement3s = (unsigned short *)element3s;
8920 rsurface.modelelement3s_indexbuffer = NULL;
8921 rsurface.modelelement3s_bufferoffset = 0;
8922 rsurface.modellightmapoffsets = NULL;
8923 rsurface.modelsurfaces = NULL;
8924 rsurface.batchgeneratedvertex = false;
8925 rsurface.batchfirstvertex = 0;
8926 rsurface.batchnumvertices = 0;
8927 rsurface.batchfirsttriangle = 0;
8928 rsurface.batchnumtriangles = 0;
8929 rsurface.batchvertex3f = NULL;
8930 rsurface.batchvertex3f_vertexbuffer = NULL;
8931 rsurface.batchvertex3f_bufferoffset = 0;
8932 rsurface.batchsvector3f = NULL;
8933 rsurface.batchsvector3f_vertexbuffer = NULL;
8934 rsurface.batchsvector3f_bufferoffset = 0;
8935 rsurface.batchtvector3f = NULL;
8936 rsurface.batchtvector3f_vertexbuffer = NULL;
8937 rsurface.batchtvector3f_bufferoffset = 0;
8938 rsurface.batchnormal3f = NULL;
8939 rsurface.batchnormal3f_vertexbuffer = NULL;
8940 rsurface.batchnormal3f_bufferoffset = 0;
8941 rsurface.batchlightmapcolor4f = NULL;
8942 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8943 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8944 rsurface.batchtexcoordtexture2f = NULL;
8945 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8946 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8947 rsurface.batchtexcoordlightmap2f = NULL;
8948 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8949 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8950 rsurface.batchskeletalindex4ub = NULL;
8951 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8952 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8953 rsurface.batchskeletalweight4ub = NULL;
8954 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8955 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8956 rsurface.batchvertexmesh = NULL;
8957 rsurface.batchvertexmesh_vertexbuffer = NULL;
8958 rsurface.batchvertexmesh_bufferoffset = 0;
8959 rsurface.batchelement3i = NULL;
8960 rsurface.batchelement3i_indexbuffer = NULL;
8961 rsurface.batchelement3i_bufferoffset = 0;
8962 rsurface.batchelement3s = NULL;
8963 rsurface.batchelement3s_indexbuffer = NULL;
8964 rsurface.batchelement3s_bufferoffset = 0;
8965 rsurface.passcolor4f = NULL;
8966 rsurface.passcolor4f_vertexbuffer = NULL;
8967 rsurface.passcolor4f_bufferoffset = 0;
8968 rsurface.forcecurrenttextureupdate = true;
8970 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8972 if ((wantnormals || wanttangents) && !normal3f)
8974 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8975 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8977 if (wanttangents && !svector3f)
8979 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8980 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8981 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8986 float RSurf_FogPoint(const float *v)
8988 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8989 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8990 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8991 float FogHeightFade = r_refdef.fogheightfade;
8993 unsigned int fogmasktableindex;
8994 if (r_refdef.fogplaneviewabove)
8995 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8997 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8998 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8999 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9002 float RSurf_FogVertex(const float *v)
9004 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9005 float FogPlaneViewDist = rsurface.fogplaneviewdist;
9006 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9007 float FogHeightFade = rsurface.fogheightfade;
9009 unsigned int fogmasktableindex;
9010 if (r_refdef.fogplaneviewabove)
9011 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9013 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9014 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9015 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9018 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
9021 for (i = 0;i < numelements;i++)
9022 outelement3i[i] = inelement3i[i] + adjust;
9025 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9026 extern cvar_t gl_vbo;
9027 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9035 int surfacefirsttriangle;
9036 int surfacenumtriangles;
9037 int surfacefirstvertex;
9038 int surfaceendvertex;
9039 int surfacenumvertices;
9040 int batchnumsurfaces = texturenumsurfaces;
9041 int batchnumvertices;
9042 int batchnumtriangles;
9046 qboolean dynamicvertex;
9050 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9053 q3shaderinfo_deform_t *deform;
9054 const msurface_t *surface, *firstsurface;
9055 r_vertexmesh_t *vertexmesh;
9056 if (!texturenumsurfaces)
9058 // find vertex range of this surface batch
9060 firstsurface = texturesurfacelist[0];
9061 firsttriangle = firstsurface->num_firsttriangle;
9062 batchnumvertices = 0;
9063 batchnumtriangles = 0;
9064 firstvertex = endvertex = firstsurface->num_firstvertex;
9065 for (i = 0;i < texturenumsurfaces;i++)
9067 surface = texturesurfacelist[i];
9068 if (surface != firstsurface + i)
9070 surfacefirstvertex = surface->num_firstvertex;
9071 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
9072 surfacenumvertices = surface->num_vertices;
9073 surfacenumtriangles = surface->num_triangles;
9074 if (firstvertex > surfacefirstvertex)
9075 firstvertex = surfacefirstvertex;
9076 if (endvertex < surfaceendvertex)
9077 endvertex = surfaceendvertex;
9078 batchnumvertices += surfacenumvertices;
9079 batchnumtriangles += surfacenumtriangles;
9082 r_refdef.stats[r_stat_batch_batches]++;
9084 r_refdef.stats[r_stat_batch_withgaps]++;
9085 r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
9086 r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
9087 r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
9089 // we now know the vertex range used, and if there are any gaps in it
9090 rsurface.batchfirstvertex = firstvertex;
9091 rsurface.batchnumvertices = endvertex - firstvertex;
9092 rsurface.batchfirsttriangle = firsttriangle;
9093 rsurface.batchnumtriangles = batchnumtriangles;
9095 // this variable holds flags for which properties have been updated that
9096 // may require regenerating vertexmesh array...
9099 // check if any dynamic vertex processing must occur
9100 dynamicvertex = false;
9102 // a cvar to force the dynamic vertex path to be taken, for debugging
9103 if (r_batch_debugdynamicvertexpath.integer)
9107 r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9108 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9109 r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9110 r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9112 dynamicvertex = true;
9115 // if there is a chance of animated vertex colors, it's a dynamic batch
9116 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9120 r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9121 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9122 r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9123 r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9125 dynamicvertex = true;
9126 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9129 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9131 switch (deform->deform)
9134 case Q3DEFORM_PROJECTIONSHADOW:
9135 case Q3DEFORM_TEXT0:
9136 case Q3DEFORM_TEXT1:
9137 case Q3DEFORM_TEXT2:
9138 case Q3DEFORM_TEXT3:
9139 case Q3DEFORM_TEXT4:
9140 case Q3DEFORM_TEXT5:
9141 case Q3DEFORM_TEXT6:
9142 case Q3DEFORM_TEXT7:
9145 case Q3DEFORM_AUTOSPRITE:
9148 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9149 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9150 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9151 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9153 dynamicvertex = true;
9154 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9155 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9157 case Q3DEFORM_AUTOSPRITE2:
9160 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9161 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9162 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9163 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9165 dynamicvertex = true;
9166 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9167 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9169 case Q3DEFORM_NORMAL:
9172 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9173 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9174 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9175 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9177 dynamicvertex = true;
9178 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9179 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9182 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9183 break; // if wavefunc is a nop, ignore this transform
9186 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9187 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9188 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9189 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9191 dynamicvertex = true;
9192 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9193 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9195 case Q3DEFORM_BULGE:
9198 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9199 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9200 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9201 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9203 dynamicvertex = true;
9204 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9205 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9208 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9209 break; // if wavefunc is a nop, ignore this transform
9212 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9213 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9214 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9215 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9217 dynamicvertex = true;
9218 batchneed |= BATCHNEED_ARRAY_VERTEX;
9219 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9223 switch(rsurface.texture->tcgen.tcgen)
9226 case Q3TCGEN_TEXTURE:
9228 case Q3TCGEN_LIGHTMAP:
9231 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9232 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9233 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9234 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9236 dynamicvertex = true;
9237 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9238 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9240 case Q3TCGEN_VECTOR:
9243 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9244 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9245 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9246 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9248 dynamicvertex = true;
9249 batchneed |= BATCHNEED_ARRAY_VERTEX;
9250 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9252 case Q3TCGEN_ENVIRONMENT:
9255 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9256 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9257 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9258 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9260 dynamicvertex = true;
9261 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9262 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9265 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9269 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9270 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9271 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9272 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9274 dynamicvertex = true;
9275 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9276 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9279 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9283 r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9284 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9285 r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9286 r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9288 dynamicvertex = true;
9289 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9292 // when the model data has no vertex buffer (dynamic mesh), we need to
9294 if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9295 batchneed |= BATCHNEED_NOGAPS;
9297 // the caller can specify BATCHNEED_NOGAPS to force a batch with
9298 // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9299 // we ensure this by treating the vertex batch as dynamic...
9300 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9304 r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9305 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9306 r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9307 r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9309 dynamicvertex = true;
9314 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9315 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
9316 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
9317 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
9318 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9319 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9320 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9321 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL) batchneed |= BATCHNEED_ARRAY_SKELETAL;
9324 // if needsupdate, we have to do a dynamic vertex batch for sure
9325 if (needsupdate & batchneed)
9329 r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9330 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9331 r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9332 r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9334 dynamicvertex = true;
9337 // see if we need to build vertexmesh from arrays
9338 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9342 r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9343 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9344 r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9345 r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9347 dynamicvertex = true;
9350 // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9351 if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9352 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9354 rsurface.batchvertex3f = rsurface.modelvertex3f;
9355 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9356 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9357 rsurface.batchsvector3f = rsurface.modelsvector3f;
9358 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9359 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9360 rsurface.batchtvector3f = rsurface.modeltvector3f;
9361 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9362 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9363 rsurface.batchnormal3f = rsurface.modelnormal3f;
9364 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9365 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9366 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9367 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
9368 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
9369 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9370 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
9371 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
9372 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9373 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9374 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9375 rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9376 rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9377 rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9378 rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9379 rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9380 rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9381 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9382 rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9383 rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9384 rsurface.batchelement3i = rsurface.modelelement3i;
9385 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9386 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9387 rsurface.batchelement3s = rsurface.modelelement3s;
9388 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9389 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9390 rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9391 rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9392 rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9393 rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9394 rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9396 // if any dynamic vertex processing has to occur in software, we copy the
9397 // entire surface list together before processing to rebase the vertices
9398 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9400 // if any gaps exist and we do not have a static vertex buffer, we have to
9401 // copy the surface list together to avoid wasting upload bandwidth on the
9402 // vertices in the gaps.
9404 // if gaps exist and we have a static vertex buffer, we can choose whether
9405 // to combine the index buffer ranges into one dynamic index buffer or
9406 // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9408 // in many cases the batch is reduced to one draw call.
9410 rsurface.batchmultidraw = false;
9411 rsurface.batchmultidrawnumsurfaces = 0;
9412 rsurface.batchmultidrawsurfacelist = NULL;
9416 // static vertex data, just set pointers...
9417 rsurface.batchgeneratedvertex = false;
9418 // if there are gaps, we want to build a combined index buffer,
9419 // otherwise use the original static buffer with an appropriate offset
9422 r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9423 r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9424 r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9425 r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9426 if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9428 rsurface.batchmultidraw = true;
9429 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9430 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9433 // build a new triangle elements array for this batch
9434 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9435 rsurface.batchfirsttriangle = 0;
9437 for (i = 0;i < texturenumsurfaces;i++)
9439 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9440 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9441 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9442 numtriangles += surfacenumtriangles;
9444 rsurface.batchelement3i_indexbuffer = NULL;
9445 rsurface.batchelement3i_bufferoffset = 0;
9446 rsurface.batchelement3s = NULL;
9447 rsurface.batchelement3s_indexbuffer = NULL;
9448 rsurface.batchelement3s_bufferoffset = 0;
9449 if (endvertex <= 65536)
9451 // make a 16bit (unsigned short) index array if possible
9452 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9453 for (i = 0;i < numtriangles*3;i++)
9454 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9456 // upload buffer data for the copytriangles batch
9457 if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9459 if (rsurface.batchelement3s)
9460 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9461 else if (rsurface.batchelement3i)
9462 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9467 r_refdef.stats[r_stat_batch_fast_batches] += 1;
9468 r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9469 r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9470 r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9475 // something needs software processing, do it for real...
9476 // we only directly handle separate array data in this case and then
9477 // generate interleaved data if needed...
9478 rsurface.batchgeneratedvertex = true;
9479 r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9480 r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9481 r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9482 r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9484 // now copy the vertex data into a combined array and make an index array
9485 // (this is what Quake3 does all the time)
9486 // we also apply any skeletal animation here that would have been done in
9487 // the vertex shader, because most of the dynamic vertex animation cases
9488 // need actual vertex positions and normals
9489 //if (dynamicvertex)
9491 rsurface.batchvertexmesh = NULL;
9492 rsurface.batchvertexmesh_vertexbuffer = NULL;
9493 rsurface.batchvertexmesh_bufferoffset = 0;
9494 rsurface.batchvertex3f = NULL;
9495 rsurface.batchvertex3f_vertexbuffer = NULL;
9496 rsurface.batchvertex3f_bufferoffset = 0;
9497 rsurface.batchsvector3f = NULL;
9498 rsurface.batchsvector3f_vertexbuffer = NULL;
9499 rsurface.batchsvector3f_bufferoffset = 0;
9500 rsurface.batchtvector3f = NULL;
9501 rsurface.batchtvector3f_vertexbuffer = NULL;
9502 rsurface.batchtvector3f_bufferoffset = 0;
9503 rsurface.batchnormal3f = NULL;
9504 rsurface.batchnormal3f_vertexbuffer = NULL;
9505 rsurface.batchnormal3f_bufferoffset = 0;
9506 rsurface.batchlightmapcolor4f = NULL;
9507 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9508 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9509 rsurface.batchtexcoordtexture2f = NULL;
9510 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9511 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9512 rsurface.batchtexcoordlightmap2f = NULL;
9513 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9514 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9515 rsurface.batchskeletalindex4ub = NULL;
9516 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9517 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9518 rsurface.batchskeletalweight4ub = NULL;
9519 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9520 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9521 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9522 rsurface.batchelement3i_indexbuffer = NULL;
9523 rsurface.batchelement3i_bufferoffset = 0;
9524 rsurface.batchelement3s = NULL;
9525 rsurface.batchelement3s_indexbuffer = NULL;
9526 rsurface.batchelement3s_bufferoffset = 0;
9527 rsurface.batchskeletaltransform3x4buffer = NULL;
9528 rsurface.batchskeletaltransform3x4offset = 0;
9529 rsurface.batchskeletaltransform3x4size = 0;
9530 // we'll only be setting up certain arrays as needed
9531 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9532 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9533 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9534 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9535 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9536 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9537 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9539 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9540 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9542 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9543 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9544 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9545 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9546 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9547 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9548 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9550 rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9551 rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9555 for (i = 0;i < texturenumsurfaces;i++)
9557 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9558 surfacenumvertices = texturesurfacelist[i]->num_vertices;
9559 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9560 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9561 // copy only the data requested
9562 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9563 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9564 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9566 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9568 if (rsurface.batchvertex3f)
9569 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9571 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9573 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9575 if (rsurface.modelnormal3f)
9576 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9578 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9580 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9582 if (rsurface.modelsvector3f)
9584 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9585 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9589 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9590 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9593 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9595 if (rsurface.modellightmapcolor4f)
9596 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9598 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9600 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9602 if (rsurface.modeltexcoordtexture2f)
9603 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9605 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9607 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9609 if (rsurface.modeltexcoordlightmap2f)
9610 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9612 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9614 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9616 if (rsurface.modelskeletalindex4ub)
9618 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9619 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9623 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9624 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9625 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9626 for (j = 0;j < surfacenumvertices;j++)
9631 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9632 numvertices += surfacenumvertices;
9633 numtriangles += surfacenumtriangles;
9636 // generate a 16bit index array as well if possible
9637 // (in general, dynamic batches fit)
9638 if (numvertices <= 65536)
9640 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9641 for (i = 0;i < numtriangles*3;i++)
9642 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9645 // since we've copied everything, the batch now starts at 0
9646 rsurface.batchfirstvertex = 0;
9647 rsurface.batchnumvertices = batchnumvertices;
9648 rsurface.batchfirsttriangle = 0;
9649 rsurface.batchnumtriangles = batchnumtriangles;
9652 // apply skeletal animation that would have been done in the vertex shader
9653 if (rsurface.batchskeletaltransform3x4)
9655 const unsigned char *si;
9656 const unsigned char *sw;
9658 const float *b = rsurface.batchskeletaltransform3x4;
9659 float *vp, *vs, *vt, *vn;
9661 float m[3][4], n[3][4];
9662 float tp[3], ts[3], tt[3], tn[3];
9663 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9664 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9665 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9666 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9667 si = rsurface.batchskeletalindex4ub;
9668 sw = rsurface.batchskeletalweight4ub;
9669 vp = rsurface.batchvertex3f;
9670 vs = rsurface.batchsvector3f;
9671 vt = rsurface.batchtvector3f;
9672 vn = rsurface.batchnormal3f;
9673 memset(m[0], 0, sizeof(m));
9674 memset(n[0], 0, sizeof(n));
9675 for (i = 0;i < batchnumvertices;i++)
9677 t[0] = b + si[0]*12;
9680 // common case - only one matrix
9694 else if (sw[2] + sw[3])
9697 t[1] = b + si[1]*12;
9698 t[2] = b + si[2]*12;
9699 t[3] = b + si[3]*12;
9700 w[0] = sw[0] * (1.0f / 255.0f);
9701 w[1] = sw[1] * (1.0f / 255.0f);
9702 w[2] = sw[2] * (1.0f / 255.0f);
9703 w[3] = sw[3] * (1.0f / 255.0f);
9704 // blend the matrices
9705 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9706 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9707 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9708 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9709 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9710 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9711 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9712 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9713 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9714 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9715 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9716 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9721 t[1] = b + si[1]*12;
9722 w[0] = sw[0] * (1.0f / 255.0f);
9723 w[1] = sw[1] * (1.0f / 255.0f);
9724 // blend the matrices
9725 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9726 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9727 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9728 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9729 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9730 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9731 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9732 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9733 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9734 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9735 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9736 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9740 // modify the vertex
9742 vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9743 vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9744 vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9748 // the normal transformation matrix is a set of cross products...
9749 CrossProduct(m[1], m[2], n[0]);
9750 CrossProduct(m[2], m[0], n[1]);
9751 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9753 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9754 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9755 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9756 VectorNormalize(vn);
9761 vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9762 vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9763 vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9764 VectorNormalize(vs);
9767 vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9768 vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9769 vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9770 VectorNormalize(vt);
9775 rsurface.batchskeletaltransform3x4 = NULL;
9776 rsurface.batchskeletalnumtransforms = 0;
9779 // q1bsp surfaces rendered in vertex color mode have to have colors
9780 // calculated based on lightstyles
9781 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9783 // generate color arrays for the surfaces in this list
9788 const unsigned char *lm;
9789 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9790 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9791 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9793 for (i = 0;i < texturenumsurfaces;i++)
9795 surface = texturesurfacelist[i];
9796 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9797 surfacenumvertices = surface->num_vertices;
9798 if (surface->lightmapinfo->samples)
9800 for (j = 0;j < surfacenumvertices;j++)
9802 lm = surface->lightmapinfo->samples + offsets[j];
9803 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9804 VectorScale(lm, scale, c);
9805 if (surface->lightmapinfo->styles[1] != 255)
9807 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9809 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9810 VectorMA(c, scale, lm, c);
9811 if (surface->lightmapinfo->styles[2] != 255)
9814 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9815 VectorMA(c, scale, lm, c);
9816 if (surface->lightmapinfo->styles[3] != 255)
9819 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9820 VectorMA(c, scale, lm, c);
9827 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);
9833 for (j = 0;j < surfacenumvertices;j++)
9835 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9842 // if vertices are deformed (sprite flares and things in maps, possibly
9843 // water waves, bulges and other deformations), modify the copied vertices
9845 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9847 switch (deform->deform)
9850 case Q3DEFORM_PROJECTIONSHADOW:
9851 case Q3DEFORM_TEXT0:
9852 case Q3DEFORM_TEXT1:
9853 case Q3DEFORM_TEXT2:
9854 case Q3DEFORM_TEXT3:
9855 case Q3DEFORM_TEXT4:
9856 case Q3DEFORM_TEXT5:
9857 case Q3DEFORM_TEXT6:
9858 case Q3DEFORM_TEXT7:
9861 case Q3DEFORM_AUTOSPRITE:
9862 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9863 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9864 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9865 VectorNormalize(newforward);
9866 VectorNormalize(newright);
9867 VectorNormalize(newup);
9868 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9869 // rsurface.batchvertex3f_vertexbuffer = NULL;
9870 // rsurface.batchvertex3f_bufferoffset = 0;
9871 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9872 // rsurface.batchsvector3f_vertexbuffer = NULL;
9873 // rsurface.batchsvector3f_bufferoffset = 0;
9874 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9875 // rsurface.batchtvector3f_vertexbuffer = NULL;
9876 // rsurface.batchtvector3f_bufferoffset = 0;
9877 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9878 // rsurface.batchnormal3f_vertexbuffer = NULL;
9879 // rsurface.batchnormal3f_bufferoffset = 0;
9880 // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9881 if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9882 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9883 if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9884 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);
9885 // a single autosprite surface can contain multiple sprites...
9886 for (j = 0;j < batchnumvertices - 3;j += 4)
9888 VectorClear(center);
9889 for (i = 0;i < 4;i++)
9890 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9891 VectorScale(center, 0.25f, center);
9892 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9893 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9894 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9895 for (i = 0;i < 4;i++)
9897 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9898 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9901 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9902 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9903 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);
9905 case Q3DEFORM_AUTOSPRITE2:
9906 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9907 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9908 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9909 VectorNormalize(newforward);
9910 VectorNormalize(newright);
9911 VectorNormalize(newup);
9912 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9913 // rsurface.batchvertex3f_vertexbuffer = NULL;
9914 // rsurface.batchvertex3f_bufferoffset = 0;
9916 const float *v1, *v2;
9926 memset(shortest, 0, sizeof(shortest));
9927 // a single autosprite surface can contain multiple sprites...
9928 for (j = 0;j < batchnumvertices - 3;j += 4)
9930 VectorClear(center);
9931 for (i = 0;i < 4;i++)
9932 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9933 VectorScale(center, 0.25f, center);
9934 // find the two shortest edges, then use them to define the
9935 // axis vectors for rotating around the central axis
9936 for (i = 0;i < 6;i++)
9938 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9939 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9940 l = VectorDistance2(v1, v2);
9941 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9943 l += (1.0f / 1024.0f);
9944 if (shortest[0].length2 > l || i == 0)
9946 shortest[1] = shortest[0];
9947 shortest[0].length2 = l;
9948 shortest[0].v1 = v1;
9949 shortest[0].v2 = v2;
9951 else if (shortest[1].length2 > l || i == 1)
9953 shortest[1].length2 = l;
9954 shortest[1].v1 = v1;
9955 shortest[1].v2 = v2;
9958 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9959 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9960 // this calculates the right vector from the shortest edge
9961 // and the up vector from the edge midpoints
9962 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9963 VectorNormalize(right);
9964 VectorSubtract(end, start, up);
9965 VectorNormalize(up);
9966 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9967 VectorSubtract(rsurface.localvieworigin, center, forward);
9968 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9969 VectorNegate(forward, forward);
9970 VectorReflect(forward, 0, up, forward);
9971 VectorNormalize(forward);
9972 CrossProduct(up, forward, newright);
9973 VectorNormalize(newright);
9974 // rotate the quad around the up axis vector, this is made
9975 // especially easy by the fact we know the quad is flat,
9976 // so we only have to subtract the center position and
9977 // measure distance along the right vector, and then
9978 // multiply that by the newright vector and add back the
9980 // we also need to subtract the old position to undo the
9981 // displacement from the center, which we do with a
9982 // DotProduct, the subtraction/addition of center is also
9983 // optimized into DotProducts here
9984 l = DotProduct(right, center);
9985 for (i = 0;i < 4;i++)
9987 v1 = rsurface.batchvertex3f + 3*(j+i);
9988 f = DotProduct(right, v1) - l;
9989 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9993 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9995 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9996 // rsurface.batchnormal3f_vertexbuffer = NULL;
9997 // rsurface.batchnormal3f_bufferoffset = 0;
9998 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10000 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10002 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10003 // rsurface.batchsvector3f_vertexbuffer = NULL;
10004 // rsurface.batchsvector3f_bufferoffset = 0;
10005 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10006 // rsurface.batchtvector3f_vertexbuffer = NULL;
10007 // rsurface.batchtvector3f_bufferoffset = 0;
10008 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);
10011 case Q3DEFORM_NORMAL:
10012 // deform the normals to make reflections wavey
10013 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10014 rsurface.batchnormal3f_vertexbuffer = NULL;
10015 rsurface.batchnormal3f_bufferoffset = 0;
10016 for (j = 0;j < batchnumvertices;j++)
10019 float *normal = rsurface.batchnormal3f + 3*j;
10020 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
10021 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10022 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10023 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10024 VectorNormalize(normal);
10026 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10028 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10029 // rsurface.batchsvector3f_vertexbuffer = NULL;
10030 // rsurface.batchsvector3f_bufferoffset = 0;
10031 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10032 // rsurface.batchtvector3f_vertexbuffer = NULL;
10033 // rsurface.batchtvector3f_bufferoffset = 0;
10034 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);
10037 case Q3DEFORM_WAVE:
10038 // deform vertex array to make wavey water and flags and such
10039 waveparms[0] = deform->waveparms[0];
10040 waveparms[1] = deform->waveparms[1];
10041 waveparms[2] = deform->waveparms[2];
10042 waveparms[3] = deform->waveparms[3];
10043 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
10044 break; // if wavefunc is a nop, don't make a dynamic vertex array
10045 // this is how a divisor of vertex influence on deformation
10046 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10047 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10048 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10049 // rsurface.batchvertex3f_vertexbuffer = NULL;
10050 // rsurface.batchvertex3f_bufferoffset = 0;
10051 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10052 // rsurface.batchnormal3f_vertexbuffer = NULL;
10053 // rsurface.batchnormal3f_bufferoffset = 0;
10054 for (j = 0;j < batchnumvertices;j++)
10056 // if the wavefunc depends on time, evaluate it per-vertex
10059 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
10060 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10062 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10064 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10065 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10066 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10068 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10069 // rsurface.batchsvector3f_vertexbuffer = NULL;
10070 // rsurface.batchsvector3f_bufferoffset = 0;
10071 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10072 // rsurface.batchtvector3f_vertexbuffer = NULL;
10073 // rsurface.batchtvector3f_bufferoffset = 0;
10074 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);
10077 case Q3DEFORM_BULGE:
10078 // deform vertex array to make the surface have moving bulges
10079 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10080 // rsurface.batchvertex3f_vertexbuffer = NULL;
10081 // rsurface.batchvertex3f_bufferoffset = 0;
10082 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10083 // rsurface.batchnormal3f_vertexbuffer = NULL;
10084 // rsurface.batchnormal3f_bufferoffset = 0;
10085 for (j = 0;j < batchnumvertices;j++)
10087 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
10088 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10090 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10091 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10092 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10094 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10095 // rsurface.batchsvector3f_vertexbuffer = NULL;
10096 // rsurface.batchsvector3f_bufferoffset = 0;
10097 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10098 // rsurface.batchtvector3f_vertexbuffer = NULL;
10099 // rsurface.batchtvector3f_bufferoffset = 0;
10100 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);
10103 case Q3DEFORM_MOVE:
10104 // deform vertex array
10105 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10106 break; // if wavefunc is a nop, don't make a dynamic vertex array
10107 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10108 VectorScale(deform->parms, scale, waveparms);
10109 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10110 // rsurface.batchvertex3f_vertexbuffer = NULL;
10111 // rsurface.batchvertex3f_bufferoffset = 0;
10112 for (j = 0;j < batchnumvertices;j++)
10113 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10118 if (rsurface.batchtexcoordtexture2f)
10120 // generate texcoords based on the chosen texcoord source
10121 switch(rsurface.texture->tcgen.tcgen)
10124 case Q3TCGEN_TEXTURE:
10126 case Q3TCGEN_LIGHTMAP:
10127 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10128 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10129 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10130 if (rsurface.batchtexcoordlightmap2f)
10131 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
10133 case Q3TCGEN_VECTOR:
10134 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10135 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10136 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10137 for (j = 0;j < batchnumvertices;j++)
10139 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
10140 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
10143 case Q3TCGEN_ENVIRONMENT:
10144 // make environment reflections using a spheremap
10145 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10146 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10147 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10148 for (j = 0;j < batchnumvertices;j++)
10150 // identical to Q3A's method, but executed in worldspace so
10151 // carried models can be shiny too
10153 float viewer[3], d, reflected[3], worldreflected[3];
10155 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10156 // VectorNormalize(viewer);
10158 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10160 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10161 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10162 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10163 // note: this is proportinal to viewer, so we can normalize later
10165 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10166 VectorNormalize(worldreflected);
10168 // note: this sphere map only uses world x and z!
10169 // so positive and negative y will LOOK THE SAME.
10170 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10171 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10175 // the only tcmod that needs software vertex processing is turbulent, so
10176 // check for it here and apply the changes if needed
10177 // and we only support that as the first one
10178 // (handling a mixture of turbulent and other tcmods would be problematic
10179 // without punting it entirely to a software path)
10180 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10182 amplitude = rsurface.texture->tcmods[0].parms[1];
10183 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
10184 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10185 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10186 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10187 for (j = 0;j < batchnumvertices;j++)
10189 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);
10190 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10195 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10197 // convert the modified arrays to vertex structs
10198 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10199 // rsurface.batchvertexmesh_vertexbuffer = NULL;
10200 // rsurface.batchvertexmesh_bufferoffset = 0;
10201 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10202 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10203 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10204 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10205 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10206 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10207 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10209 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10211 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10212 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10215 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10216 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10217 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10218 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10219 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10220 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10221 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10222 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10223 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10224 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10226 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10228 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10229 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10234 // upload buffer data for the dynamic batch
10235 if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10237 if (rsurface.batchvertexmesh)
10238 rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10241 if (rsurface.batchvertex3f)
10242 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10243 if (rsurface.batchsvector3f)
10244 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10245 if (rsurface.batchtvector3f)
10246 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10247 if (rsurface.batchnormal3f)
10248 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10249 if (rsurface.batchlightmapcolor4f)
10250 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10251 if (rsurface.batchtexcoordtexture2f)
10252 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10253 if (rsurface.batchtexcoordlightmap2f)
10254 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10255 if (rsurface.batchskeletalindex4ub)
10256 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10257 if (rsurface.batchskeletalweight4ub)
10258 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10260 if (rsurface.batchelement3s)
10261 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10262 else if (rsurface.batchelement3i)
10263 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10267 void RSurf_DrawBatch(void)
10269 // sometimes a zero triangle surface (usually a degenerate patch) makes it
10270 // through the pipeline, killing it earlier in the pipeline would have
10271 // per-surface overhead rather than per-batch overhead, so it's best to
10272 // reject it here, before it hits glDraw.
10273 if (rsurface.batchnumtriangles == 0)
10276 // batch debugging code
10277 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10283 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10284 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10287 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10289 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10291 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10292 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);
10299 if (rsurface.batchmultidraw)
10301 // issue multiple draws rather than copying index data
10302 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10303 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10304 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10305 for (i = 0;i < numsurfaces;)
10307 // combine consecutive surfaces as one draw
10308 for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10309 if (surfacelist[j] != surfacelist[k] + 1)
10311 firstvertex = surfacelist[i]->num_firstvertex;
10312 endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10313 firsttriangle = surfacelist[i]->num_firsttriangle;
10314 endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10315 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);
10321 // there is only one consecutive run of index data (may have been combined)
10322 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);
10326 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10328 // pick the closest matching water plane
10329 int planeindex, vertexindex, bestplaneindex = -1;
10333 r_waterstate_waterplane_t *p;
10334 qboolean prepared = false;
10336 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10338 if(p->camera_entity != rsurface.texture->camera_entity)
10343 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10345 if(rsurface.batchnumvertices == 0)
10348 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10350 Matrix4x4_Transform(&rsurface.matrix, v, vert);
10351 d += fabs(PlaneDiff(vert, &p->plane));
10353 if (bestd > d || bestplaneindex < 0)
10356 bestplaneindex = planeindex;
10359 return bestplaneindex;
10360 // NOTE: this MAY return a totally unrelated water plane; we can ignore
10361 // this situation though, as it might be better to render single larger
10362 // batches with useless stuff (backface culled for example) than to
10363 // render multiple smaller batches
10366 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10369 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10370 rsurface.passcolor4f_vertexbuffer = 0;
10371 rsurface.passcolor4f_bufferoffset = 0;
10372 for (i = 0;i < rsurface.batchnumvertices;i++)
10373 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10376 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10383 if (rsurface.passcolor4f)
10385 // generate color arrays
10386 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10387 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10388 rsurface.passcolor4f_vertexbuffer = 0;
10389 rsurface.passcolor4f_bufferoffset = 0;
10390 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)
10392 f = RSurf_FogVertex(v);
10401 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10402 rsurface.passcolor4f_vertexbuffer = 0;
10403 rsurface.passcolor4f_bufferoffset = 0;
10404 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10406 f = RSurf_FogVertex(v);
10415 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10422 if (!rsurface.passcolor4f)
10424 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10425 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10426 rsurface.passcolor4f_vertexbuffer = 0;
10427 rsurface.passcolor4f_bufferoffset = 0;
10428 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)
10430 f = RSurf_FogVertex(v);
10431 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10432 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10433 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10438 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10443 if (!rsurface.passcolor4f)
10445 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10446 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10447 rsurface.passcolor4f_vertexbuffer = 0;
10448 rsurface.passcolor4f_bufferoffset = 0;
10449 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10458 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10463 if (!rsurface.passcolor4f)
10465 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10466 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10467 rsurface.passcolor4f_vertexbuffer = 0;
10468 rsurface.passcolor4f_bufferoffset = 0;
10469 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10471 c2[0] = c[0] + r_refdef.scene.ambient;
10472 c2[1] = c[1] + r_refdef.scene.ambient;
10473 c2[2] = c[2] + r_refdef.scene.ambient;
10478 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10481 rsurface.passcolor4f = NULL;
10482 rsurface.passcolor4f_vertexbuffer = 0;
10483 rsurface.passcolor4f_bufferoffset = 0;
10484 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10485 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10486 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10487 GL_Color(r, g, b, a);
10488 R_Mesh_TexBind(0, rsurface.lightmaptexture);
10489 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10490 R_Mesh_TexMatrix(0, NULL);
10494 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10496 // TODO: optimize applyfog && applycolor case
10497 // just apply fog if necessary, and tint the fog color array if necessary
10498 rsurface.passcolor4f = NULL;
10499 rsurface.passcolor4f_vertexbuffer = 0;
10500 rsurface.passcolor4f_bufferoffset = 0;
10501 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10502 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10503 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10504 GL_Color(r, g, b, a);
10508 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10511 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10512 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10513 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10514 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10515 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10516 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10517 GL_Color(r, g, b, a);
10521 static void RSurf_DrawBatch_GL11_ClampColor(void)
10526 if (!rsurface.passcolor4f)
10528 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10530 c2[0] = bound(0.0f, c1[0], 1.0f);
10531 c2[1] = bound(0.0f, c1[1], 1.0f);
10532 c2[2] = bound(0.0f, c1[2], 1.0f);
10533 c2[3] = bound(0.0f, c1[3], 1.0f);
10537 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10547 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10548 rsurface.passcolor4f_vertexbuffer = 0;
10549 rsurface.passcolor4f_bufferoffset = 0;
10550 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)
10552 f = -DotProduct(r_refdef.view.forward, n);
10554 f = f * 0.85 + 0.15; // work around so stuff won't get black
10555 f *= r_refdef.lightmapintensity;
10556 Vector4Set(c, f, f, f, 1);
10560 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10562 RSurf_DrawBatch_GL11_ApplyFakeLight();
10563 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10564 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10565 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10566 GL_Color(r, g, b, a);
10570 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10578 vec3_t ambientcolor;
10579 vec3_t diffusecolor;
10583 VectorCopy(rsurface.modellight_lightdir, lightdir);
10584 f = 0.5f * r_refdef.lightmapintensity;
10585 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10586 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10587 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10588 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10589 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10590 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10592 if (VectorLength2(diffusecolor) > 0)
10594 // q3-style directional shading
10595 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10596 rsurface.passcolor4f_vertexbuffer = 0;
10597 rsurface.passcolor4f_bufferoffset = 0;
10598 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)
10600 if ((f = DotProduct(n, lightdir)) > 0)
10601 VectorMA(ambientcolor, f, diffusecolor, c);
10603 VectorCopy(ambientcolor, c);
10610 *applycolor = false;
10614 *r = ambientcolor[0];
10615 *g = ambientcolor[1];
10616 *b = ambientcolor[2];
10617 rsurface.passcolor4f = NULL;
10618 rsurface.passcolor4f_vertexbuffer = 0;
10619 rsurface.passcolor4f_bufferoffset = 0;
10623 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10625 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10626 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10627 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10628 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10629 GL_Color(r, g, b, a);
10633 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10641 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10642 rsurface.passcolor4f_vertexbuffer = 0;
10643 rsurface.passcolor4f_bufferoffset = 0;
10645 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10647 f = 1 - RSurf_FogVertex(v);
10655 void RSurf_SetupDepthAndCulling(void)
10657 // submodels are biased to avoid z-fighting with world surfaces that they
10658 // may be exactly overlapping (avoids z-fighting artifacts on certain
10659 // doors and things in Quake maps)
10660 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10661 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10662 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10663 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10666 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10668 // transparent sky would be ridiculous
10669 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10671 R_SetupShader_Generic_NoTexture(false, false);
10672 skyrenderlater = true;
10673 RSurf_SetupDepthAndCulling();
10674 GL_DepthMask(true);
10675 // LordHavoc: HalfLife maps have freaky skypolys so don't use
10676 // skymasking on them, and Quake3 never did sky masking (unlike
10677 // software Quake and software Quake2), so disable the sky masking
10678 // in Quake3 maps as it causes problems with q3map2 sky tricks,
10679 // and skymasking also looks very bad when noclipping outside the
10680 // level, so don't use it then either.
10681 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.skymasking && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10683 R_Mesh_ResetTextureState();
10684 if (skyrendermasked)
10686 R_SetupShader_DepthOrShadow(false, false, false);
10687 // depth-only (masking)
10688 GL_ColorMask(0,0,0,0);
10689 // just to make sure that braindead drivers don't draw
10690 // anything despite that colormask...
10691 GL_BlendFunc(GL_ZERO, GL_ONE);
10692 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10693 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10697 R_SetupShader_Generic_NoTexture(false, false);
10699 GL_BlendFunc(GL_ONE, GL_ZERO);
10700 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10701 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10702 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10705 if (skyrendermasked)
10706 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10708 R_Mesh_ResetTextureState();
10709 GL_Color(1, 1, 1, 1);
10712 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10713 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10714 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10716 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10720 // render screenspace normalmap to texture
10721 GL_DepthMask(true);
10722 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10727 // bind lightmap texture
10729 // water/refraction/reflection/camera surfaces have to be handled specially
10730 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10732 int start, end, startplaneindex;
10733 for (start = 0;start < texturenumsurfaces;start = end)
10735 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10736 if(startplaneindex < 0)
10738 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10739 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10743 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10745 // now that we have a batch using the same planeindex, render it
10746 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10748 // render water or distortion background
10749 GL_DepthMask(true);
10750 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);
10752 // blend surface on top
10753 GL_DepthMask(false);
10754 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10757 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10759 // render surface with reflection texture as input
10760 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10761 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);
10768 // render surface batch normally
10769 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10770 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);
10774 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10776 // OpenGL 1.3 path - anything not completely ancient
10777 qboolean applycolor;
10780 const texturelayer_t *layer;
10781 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);
10782 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10784 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10787 int layertexrgbscale;
10788 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10790 if (layerindex == 0)
10791 GL_AlphaTest(true);
10794 GL_AlphaTest(false);
10795 GL_DepthFunc(GL_EQUAL);
10798 GL_DepthMask(layer->depthmask && writedepth);
10799 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10800 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10802 layertexrgbscale = 4;
10803 VectorScale(layer->color, 0.25f, layercolor);
10805 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10807 layertexrgbscale = 2;
10808 VectorScale(layer->color, 0.5f, layercolor);
10812 layertexrgbscale = 1;
10813 VectorScale(layer->color, 1.0f, layercolor);
10815 layercolor[3] = layer->color[3];
10816 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10817 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10818 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10819 switch (layer->type)
10821 case TEXTURELAYERTYPE_LITTEXTURE:
10822 // single-pass lightmapped texture with 2x rgbscale
10823 R_Mesh_TexBind(0, r_texture_white);
10824 R_Mesh_TexMatrix(0, NULL);
10825 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10826 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10827 R_Mesh_TexBind(1, layer->texture);
10828 R_Mesh_TexMatrix(1, &layer->texmatrix);
10829 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10830 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10831 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10832 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10833 else if (FAKELIGHT_ENABLED)
10834 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10835 else if (rsurface.uselightmaptexture)
10836 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10838 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10840 case TEXTURELAYERTYPE_TEXTURE:
10841 // singletexture unlit texture with transparency support
10842 R_Mesh_TexBind(0, layer->texture);
10843 R_Mesh_TexMatrix(0, &layer->texmatrix);
10844 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10845 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10846 R_Mesh_TexBind(1, 0);
10847 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10848 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10850 case TEXTURELAYERTYPE_FOG:
10851 // singletexture fogging
10852 if (layer->texture)
10854 R_Mesh_TexBind(0, layer->texture);
10855 R_Mesh_TexMatrix(0, &layer->texmatrix);
10856 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10857 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10861 R_Mesh_TexBind(0, 0);
10862 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10864 R_Mesh_TexBind(1, 0);
10865 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10866 // generate a color array for the fog pass
10867 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10868 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10872 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10875 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10877 GL_DepthFunc(GL_LEQUAL);
10878 GL_AlphaTest(false);
10882 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10884 // OpenGL 1.1 - crusty old voodoo path
10887 const texturelayer_t *layer;
10888 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);
10889 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10891 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10893 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10895 if (layerindex == 0)
10896 GL_AlphaTest(true);
10899 GL_AlphaTest(false);
10900 GL_DepthFunc(GL_EQUAL);
10903 GL_DepthMask(layer->depthmask && writedepth);
10904 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10905 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10906 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10907 switch (layer->type)
10909 case TEXTURELAYERTYPE_LITTEXTURE:
10910 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10912 // two-pass lit texture with 2x rgbscale
10913 // first the lightmap pass
10914 R_Mesh_TexBind(0, r_texture_white);
10915 R_Mesh_TexMatrix(0, NULL);
10916 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10917 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10918 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10919 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10920 else if (FAKELIGHT_ENABLED)
10921 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10922 else if (rsurface.uselightmaptexture)
10923 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10925 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10926 // then apply the texture to it
10927 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10928 R_Mesh_TexBind(0, layer->texture);
10929 R_Mesh_TexMatrix(0, &layer->texmatrix);
10930 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10931 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10932 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);
10936 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10937 R_Mesh_TexBind(0, layer->texture);
10938 R_Mesh_TexMatrix(0, &layer->texmatrix);
10939 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10940 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10941 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10942 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);
10943 else if (FAKELIGHT_ENABLED)
10944 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);
10946 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);
10949 case TEXTURELAYERTYPE_TEXTURE:
10950 // singletexture unlit texture with transparency support
10951 R_Mesh_TexBind(0, layer->texture);
10952 R_Mesh_TexMatrix(0, &layer->texmatrix);
10953 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10954 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10955 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);
10957 case TEXTURELAYERTYPE_FOG:
10958 // singletexture fogging
10959 if (layer->texture)
10961 R_Mesh_TexBind(0, layer->texture);
10962 R_Mesh_TexMatrix(0, &layer->texmatrix);
10963 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10964 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10968 R_Mesh_TexBind(0, 0);
10969 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10971 // generate a color array for the fog pass
10972 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10973 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10977 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10980 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10982 GL_DepthFunc(GL_LEQUAL);
10983 GL_AlphaTest(false);
10987 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10991 r_vertexgeneric_t *batchvertex;
10994 // R_Mesh_ResetTextureState();
10995 R_SetupShader_Generic_NoTexture(false, false);
10997 if(rsurface.texture && rsurface.texture->currentskinframe)
10999 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
11000 c[3] *= rsurface.texture->currentalpha;
11010 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
11012 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
11013 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
11014 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
11017 // brighten it up (as texture value 127 means "unlit")
11018 c[0] *= 2 * r_refdef.view.colorscale;
11019 c[1] *= 2 * r_refdef.view.colorscale;
11020 c[2] *= 2 * r_refdef.view.colorscale;
11022 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11023 c[3] *= r_wateralpha.value;
11025 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11027 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11028 GL_DepthMask(false);
11030 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11032 GL_BlendFunc(GL_ONE, GL_ONE);
11033 GL_DepthMask(false);
11035 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11037 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11038 GL_DepthMask(false);
11040 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11042 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11043 GL_DepthMask(false);
11047 GL_BlendFunc(GL_ONE, GL_ZERO);
11048 GL_DepthMask(writedepth);
11051 if (r_showsurfaces.integer == 3)
11053 rsurface.passcolor4f = NULL;
11055 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11057 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11059 rsurface.passcolor4f = NULL;
11060 rsurface.passcolor4f_vertexbuffer = 0;
11061 rsurface.passcolor4f_bufferoffset = 0;
11063 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11065 qboolean applycolor = true;
11068 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11070 r_refdef.lightmapintensity = 1;
11071 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
11072 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11074 else if (FAKELIGHT_ENABLED)
11076 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11078 r_refdef.lightmapintensity = r_fakelight_intensity.value;
11079 RSurf_DrawBatch_GL11_ApplyFakeLight();
11080 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11084 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11086 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11087 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11088 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11091 if(!rsurface.passcolor4f)
11092 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11094 RSurf_DrawBatch_GL11_ApplyAmbient();
11095 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11096 if(r_refdef.fogenabled)
11097 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11098 RSurf_DrawBatch_GL11_ClampColor();
11100 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11101 R_SetupShader_Generic_NoTexture(false, false);
11104 else if (!r_refdef.view.showdebug)
11106 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11107 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11108 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11110 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11111 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11113 R_Mesh_PrepareVertices_Generic_Unlock();
11116 else if (r_showsurfaces.integer == 4)
11118 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11119 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11120 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11122 unsigned char c = (vi << 3) * (1.0f / 256.0f);
11123 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11124 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
11126 R_Mesh_PrepareVertices_Generic_Unlock();
11129 else if (r_showsurfaces.integer == 2)
11132 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11133 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11134 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11136 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11137 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11138 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11139 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11140 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
11141 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
11142 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
11144 R_Mesh_PrepareVertices_Generic_Unlock();
11145 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11149 int texturesurfaceindex;
11151 const msurface_t *surface;
11152 float surfacecolor4f[4];
11153 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11154 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11156 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11158 surface = texturesurfacelist[texturesurfaceindex];
11159 k = (int)(((size_t)surface) / sizeof(msurface_t));
11160 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11161 for (j = 0;j < surface->num_vertices;j++)
11163 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11164 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11168 R_Mesh_PrepareVertices_Generic_Unlock();
11173 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11176 RSurf_SetupDepthAndCulling();
11177 if (r_showsurfaces.integer)
11179 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11182 switch (vid.renderpath)
11184 case RENDERPATH_GL20:
11185 case RENDERPATH_D3D9:
11186 case RENDERPATH_D3D10:
11187 case RENDERPATH_D3D11:
11188 case RENDERPATH_SOFT:
11189 case RENDERPATH_GLES2:
11190 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11192 case RENDERPATH_GL13:
11193 case RENDERPATH_GLES1:
11194 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11196 case RENDERPATH_GL11:
11197 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11203 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11206 RSurf_SetupDepthAndCulling();
11207 if (r_showsurfaces.integer)
11209 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11212 switch (vid.renderpath)
11214 case RENDERPATH_GL20:
11215 case RENDERPATH_D3D9:
11216 case RENDERPATH_D3D10:
11217 case RENDERPATH_D3D11:
11218 case RENDERPATH_SOFT:
11219 case RENDERPATH_GLES2:
11220 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11222 case RENDERPATH_GL13:
11223 case RENDERPATH_GLES1:
11224 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11226 case RENDERPATH_GL11:
11227 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11233 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11236 int texturenumsurfaces, endsurface;
11237 texture_t *texture;
11238 const msurface_t *surface;
11239 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11241 // if the model is static it doesn't matter what value we give for
11242 // wantnormals and wanttangents, so this logic uses only rules applicable
11243 // to a model, knowing that they are meaningless otherwise
11244 if (ent == r_refdef.scene.worldentity)
11245 RSurf_ActiveWorldEntity();
11246 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11247 RSurf_ActiveModelEntity(ent, false, false, false);
11250 switch (vid.renderpath)
11252 case RENDERPATH_GL20:
11253 case RENDERPATH_D3D9:
11254 case RENDERPATH_D3D10:
11255 case RENDERPATH_D3D11:
11256 case RENDERPATH_SOFT:
11257 case RENDERPATH_GLES2:
11258 RSurf_ActiveModelEntity(ent, true, true, false);
11260 case RENDERPATH_GL11:
11261 case RENDERPATH_GL13:
11262 case RENDERPATH_GLES1:
11263 RSurf_ActiveModelEntity(ent, true, false, false);
11268 if (r_transparentdepthmasking.integer)
11270 qboolean setup = false;
11271 for (i = 0;i < numsurfaces;i = j)
11274 surface = rsurface.modelsurfaces + surfacelist[i];
11275 texture = surface->texture;
11276 rsurface.texture = R_GetCurrentTexture(texture);
11277 rsurface.lightmaptexture = NULL;
11278 rsurface.deluxemaptexture = NULL;
11279 rsurface.uselightmaptexture = false;
11280 // scan ahead until we find a different texture
11281 endsurface = min(i + 1024, numsurfaces);
11282 texturenumsurfaces = 0;
11283 texturesurfacelist[texturenumsurfaces++] = surface;
11284 for (;j < endsurface;j++)
11286 surface = rsurface.modelsurfaces + surfacelist[j];
11287 if (texture != surface->texture)
11289 texturesurfacelist[texturenumsurfaces++] = surface;
11291 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11293 // render the range of surfaces as depth
11297 GL_ColorMask(0,0,0,0);
11299 GL_DepthTest(true);
11300 GL_BlendFunc(GL_ONE, GL_ZERO);
11301 GL_DepthMask(true);
11302 // R_Mesh_ResetTextureState();
11304 RSurf_SetupDepthAndCulling();
11305 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11306 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11307 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11311 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11314 for (i = 0;i < numsurfaces;i = j)
11317 surface = rsurface.modelsurfaces + surfacelist[i];
11318 texture = surface->texture;
11319 rsurface.texture = R_GetCurrentTexture(texture);
11320 // scan ahead until we find a different texture
11321 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11322 texturenumsurfaces = 0;
11323 texturesurfacelist[texturenumsurfaces++] = surface;
11324 if(FAKELIGHT_ENABLED)
11326 rsurface.lightmaptexture = NULL;
11327 rsurface.deluxemaptexture = NULL;
11328 rsurface.uselightmaptexture = false;
11329 for (;j < endsurface;j++)
11331 surface = rsurface.modelsurfaces + surfacelist[j];
11332 if (texture != surface->texture)
11334 texturesurfacelist[texturenumsurfaces++] = surface;
11339 rsurface.lightmaptexture = surface->lightmaptexture;
11340 rsurface.deluxemaptexture = surface->deluxemaptexture;
11341 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11342 for (;j < endsurface;j++)
11344 surface = rsurface.modelsurfaces + surfacelist[j];
11345 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11347 texturesurfacelist[texturenumsurfaces++] = surface;
11350 // render the range of surfaces
11351 if (ent == r_refdef.scene.worldentity)
11352 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11354 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11356 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11359 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11361 // transparent surfaces get pushed off into the transparent queue
11362 int surfacelistindex;
11363 const msurface_t *surface;
11364 vec3_t tempcenter, center;
11365 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11367 surface = texturesurfacelist[surfacelistindex];
11368 if (r_transparent_sortsurfacesbynearest.integer)
11370 tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11371 tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11372 tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11376 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11377 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11378 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11380 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11381 if (rsurface.entity->transparent_offset) // transparent offset
11383 center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11384 center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11385 center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11387 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);
11391 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11393 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11395 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11397 RSurf_SetupDepthAndCulling();
11398 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11399 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11400 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11404 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11408 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11411 if (!rsurface.texture->currentnumlayers)
11413 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11414 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11416 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11418 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11419 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11420 else if (!rsurface.texture->currentnumlayers)
11422 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11424 // in the deferred case, transparent surfaces were queued during prepass
11425 if (!r_shadow_usingdeferredprepass)
11426 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11430 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11431 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11436 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11439 texture_t *texture;
11440 R_FrameData_SetMark();
11441 // break the surface list down into batches by texture and use of lightmapping
11442 for (i = 0;i < numsurfaces;i = j)
11445 // texture is the base texture pointer, rsurface.texture is the
11446 // current frame/skin the texture is directing us to use (for example
11447 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11448 // use skin 1 instead)
11449 texture = surfacelist[i]->texture;
11450 rsurface.texture = R_GetCurrentTexture(texture);
11451 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11453 // if this texture is not the kind we want, skip ahead to the next one
11454 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11458 if(FAKELIGHT_ENABLED || depthonly || prepass)
11460 rsurface.lightmaptexture = NULL;
11461 rsurface.deluxemaptexture = NULL;
11462 rsurface.uselightmaptexture = false;
11463 // simply scan ahead until we find a different texture or lightmap state
11464 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11469 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11470 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11471 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11472 // simply scan ahead until we find a different texture or lightmap state
11473 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11476 // render the range of surfaces
11477 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11479 R_FrameData_ReturnToMark();
11482 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11486 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11489 if (!rsurface.texture->currentnumlayers)
11491 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11492 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11494 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11496 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11497 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11498 else if (!rsurface.texture->currentnumlayers)
11500 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11502 // in the deferred case, transparent surfaces were queued during prepass
11503 if (!r_shadow_usingdeferredprepass)
11504 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11508 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11509 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11514 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11517 texture_t *texture;
11518 R_FrameData_SetMark();
11519 // break the surface list down into batches by texture and use of lightmapping
11520 for (i = 0;i < numsurfaces;i = j)
11523 // texture is the base texture pointer, rsurface.texture is the
11524 // current frame/skin the texture is directing us to use (for example
11525 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11526 // use skin 1 instead)
11527 texture = surfacelist[i]->texture;
11528 rsurface.texture = R_GetCurrentTexture(texture);
11529 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11531 // if this texture is not the kind we want, skip ahead to the next one
11532 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11536 if(FAKELIGHT_ENABLED || depthonly || prepass)
11538 rsurface.lightmaptexture = NULL;
11539 rsurface.deluxemaptexture = NULL;
11540 rsurface.uselightmaptexture = false;
11541 // simply scan ahead until we find a different texture or lightmap state
11542 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11547 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11548 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11549 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11550 // simply scan ahead until we find a different texture or lightmap state
11551 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11554 // render the range of surfaces
11555 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11557 R_FrameData_ReturnToMark();
11560 float locboxvertex3f[6*4*3] =
11562 1,0,1, 1,0,0, 1,1,0, 1,1,1,
11563 0,1,1, 0,1,0, 0,0,0, 0,0,1,
11564 1,1,1, 1,1,0, 0,1,0, 0,1,1,
11565 0,0,1, 0,0,0, 1,0,0, 1,0,1,
11566 0,0,1, 1,0,1, 1,1,1, 0,1,1,
11567 1,0,0, 0,0,0, 0,1,0, 1,1,0
11570 unsigned short locboxelements[6*2*3] =
11575 12,13,14, 12,14,15,
11576 16,17,18, 16,18,19,
11580 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11583 cl_locnode_t *loc = (cl_locnode_t *)ent;
11585 float vertex3f[6*4*3];
11587 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11588 GL_DepthMask(false);
11589 GL_DepthRange(0, 1);
11590 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11591 GL_DepthTest(true);
11592 GL_CullFace(GL_NONE);
11593 R_EntityMatrix(&identitymatrix);
11595 // R_Mesh_ResetTextureState();
11597 i = surfacelist[0];
11598 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11599 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11600 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11601 surfacelist[0] < 0 ? 0.5f : 0.125f);
11603 if (VectorCompare(loc->mins, loc->maxs))
11605 VectorSet(size, 2, 2, 2);
11606 VectorMA(loc->mins, -0.5f, size, mins);
11610 VectorCopy(loc->mins, mins);
11611 VectorSubtract(loc->maxs, loc->mins, size);
11614 for (i = 0;i < 6*4*3;)
11615 for (j = 0;j < 3;j++, i++)
11616 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11618 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11619 R_SetupShader_Generic_NoTexture(false, false);
11620 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11623 void R_DrawLocs(void)
11626 cl_locnode_t *loc, *nearestloc;
11628 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11629 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11631 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11632 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11636 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11638 if (decalsystem->decals)
11639 Mem_Free(decalsystem->decals);
11640 memset(decalsystem, 0, sizeof(*decalsystem));
11643 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, unsigned int decalsequence)
11646 tridecal_t *decals;
11649 // expand or initialize the system
11650 if (decalsystem->maxdecals <= decalsystem->numdecals)
11652 decalsystem_t old = *decalsystem;
11653 qboolean useshortelements;
11654 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11655 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11656 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)));
11657 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11658 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11659 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11660 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11661 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11662 if (decalsystem->numdecals)
11663 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11665 Mem_Free(old.decals);
11666 for (i = 0;i < decalsystem->maxdecals*3;i++)
11667 decalsystem->element3i[i] = i;
11668 if (useshortelements)
11669 for (i = 0;i < decalsystem->maxdecals*3;i++)
11670 decalsystem->element3s[i] = i;
11673 // grab a decal and search for another free slot for the next one
11674 decals = decalsystem->decals;
11675 decal = decalsystem->decals + (i = decalsystem->freedecal++);
11676 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11678 decalsystem->freedecal = i;
11679 if (decalsystem->numdecals <= i)
11680 decalsystem->numdecals = i + 1;
11682 // initialize the decal
11684 decal->triangleindex = triangleindex;
11685 decal->surfaceindex = surfaceindex;
11686 decal->decalsequence = decalsequence;
11687 decal->color4f[0][0] = c0[0];
11688 decal->color4f[0][1] = c0[1];
11689 decal->color4f[0][2] = c0[2];
11690 decal->color4f[0][3] = 1;
11691 decal->color4f[1][0] = c1[0];
11692 decal->color4f[1][1] = c1[1];
11693 decal->color4f[1][2] = c1[2];
11694 decal->color4f[1][3] = 1;
11695 decal->color4f[2][0] = c2[0];
11696 decal->color4f[2][1] = c2[1];
11697 decal->color4f[2][2] = c2[2];
11698 decal->color4f[2][3] = 1;
11699 decal->vertex3f[0][0] = v0[0];
11700 decal->vertex3f[0][1] = v0[1];
11701 decal->vertex3f[0][2] = v0[2];
11702 decal->vertex3f[1][0] = v1[0];
11703 decal->vertex3f[1][1] = v1[1];
11704 decal->vertex3f[1][2] = v1[2];
11705 decal->vertex3f[2][0] = v2[0];
11706 decal->vertex3f[2][1] = v2[1];
11707 decal->vertex3f[2][2] = v2[2];
11708 decal->texcoord2f[0][0] = t0[0];
11709 decal->texcoord2f[0][1] = t0[1];
11710 decal->texcoord2f[1][0] = t1[0];
11711 decal->texcoord2f[1][1] = t1[1];
11712 decal->texcoord2f[2][0] = t2[0];
11713 decal->texcoord2f[2][1] = t2[1];
11714 TriangleNormal(v0, v1, v2, decal->plane);
11715 VectorNormalize(decal->plane);
11716 decal->plane[3] = DotProduct(v0, decal->plane);
11719 extern cvar_t cl_decals_bias;
11720 extern cvar_t cl_decals_models;
11721 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11722 // baseparms, parms, temps
11723 static void R_DecalSystem_SplatTriangle(decalsystem_t *decalsystem, float r, float g, float b, float a, float s1, float t1, float s2, float t2, unsigned int decalsequence, qboolean dynamic, float (*planes)[4], matrix4x4_t *projection, int triangleindex, int surfaceindex)
11728 const float *vertex3f;
11729 const float *normal3f;
11731 float points[2][9][3];
11738 e = rsurface.modelelement3i + 3*triangleindex;
11740 vertex3f = rsurface.modelvertex3f;
11741 normal3f = rsurface.modelnormal3f;
11745 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11747 index = 3*e[cornerindex];
11748 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11753 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11755 index = 3*e[cornerindex];
11756 VectorCopy(vertex3f + index, v[cornerindex]);
11761 //TriangleNormal(v[0], v[1], v[2], normal);
11762 //if (DotProduct(normal, localnormal) < 0.0f)
11764 // clip by each of the box planes formed from the projection matrix
11765 // if anything survives, we emit the decal
11766 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]);
11769 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]);
11772 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]);
11775 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]);
11778 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]);
11781 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]);
11784 // some part of the triangle survived, so we have to accept it...
11787 // dynamic always uses the original triangle
11789 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11791 index = 3*e[cornerindex];
11792 VectorCopy(vertex3f + index, v[cornerindex]);
11795 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11797 // convert vertex positions to texcoords
11798 Matrix4x4_Transform(projection, v[cornerindex], temp);
11799 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11800 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11801 // calculate distance fade from the projection origin
11802 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11803 f = bound(0.0f, f, 1.0f);
11804 c[cornerindex][0] = r * f;
11805 c[cornerindex][1] = g * f;
11806 c[cornerindex][2] = b * f;
11807 c[cornerindex][3] = 1.0f;
11808 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11811 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);
11813 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11814 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);
11816 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, unsigned int decalsequence)
11818 matrix4x4_t projection;
11819 decalsystem_t *decalsystem;
11822 const msurface_t *surface;
11823 const msurface_t *surfaces;
11824 const int *surfacelist;
11825 const texture_t *texture;
11827 int numsurfacelist;
11828 int surfacelistindex;
11831 float localorigin[3];
11832 float localnormal[3];
11833 float localmins[3];
11834 float localmaxs[3];
11837 float planes[6][4];
11840 int bih_triangles_count;
11841 int bih_triangles[256];
11842 int bih_surfaces[256];
11844 decalsystem = &ent->decalsystem;
11845 model = ent->model;
11846 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11848 R_DecalSystem_Reset(&ent->decalsystem);
11852 if (!model->brush.data_leafs && !cl_decals_models.integer)
11854 if (decalsystem->model)
11855 R_DecalSystem_Reset(decalsystem);
11859 if (decalsystem->model != model)
11860 R_DecalSystem_Reset(decalsystem);
11861 decalsystem->model = model;
11863 RSurf_ActiveModelEntity(ent, true, false, false);
11865 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11866 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11867 VectorNormalize(localnormal);
11868 localsize = worldsize*rsurface.inversematrixscale;
11869 localmins[0] = localorigin[0] - localsize;
11870 localmins[1] = localorigin[1] - localsize;
11871 localmins[2] = localorigin[2] - localsize;
11872 localmaxs[0] = localorigin[0] + localsize;
11873 localmaxs[1] = localorigin[1] + localsize;
11874 localmaxs[2] = localorigin[2] + localsize;
11876 //VectorCopy(localnormal, planes[4]);
11877 //VectorVectors(planes[4], planes[2], planes[0]);
11878 AnglesFromVectors(angles, localnormal, NULL, false);
11879 AngleVectors(angles, planes[0], planes[2], planes[4]);
11880 VectorNegate(planes[0], planes[1]);
11881 VectorNegate(planes[2], planes[3]);
11882 VectorNegate(planes[4], planes[5]);
11883 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11884 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11885 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11886 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11887 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11888 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11893 matrix4x4_t forwardprojection;
11894 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11895 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11900 float projectionvector[4][3];
11901 VectorScale(planes[0], ilocalsize, projectionvector[0]);
11902 VectorScale(planes[2], ilocalsize, projectionvector[1]);
11903 VectorScale(planes[4], ilocalsize, projectionvector[2]);
11904 projectionvector[0][0] = planes[0][0] * ilocalsize;
11905 projectionvector[0][1] = planes[1][0] * ilocalsize;
11906 projectionvector[0][2] = planes[2][0] * ilocalsize;
11907 projectionvector[1][0] = planes[0][1] * ilocalsize;
11908 projectionvector[1][1] = planes[1][1] * ilocalsize;
11909 projectionvector[1][2] = planes[2][1] * ilocalsize;
11910 projectionvector[2][0] = planes[0][2] * ilocalsize;
11911 projectionvector[2][1] = planes[1][2] * ilocalsize;
11912 projectionvector[2][2] = planes[2][2] * ilocalsize;
11913 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11914 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11915 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11916 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11920 dynamic = model->surfmesh.isanimated;
11921 numsurfacelist = model->nummodelsurfaces;
11922 surfacelist = model->sortedmodelsurfaces;
11923 surfaces = model->data_surfaces;
11926 bih_triangles_count = -1;
11929 if(model->render_bih.numleafs)
11930 bih = &model->render_bih;
11931 else if(model->collision_bih.numleafs)
11932 bih = &model->collision_bih;
11935 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11936 if(bih_triangles_count == 0)
11938 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11940 if(bih_triangles_count > 0)
11942 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11944 surfaceindex = bih_surfaces[triangleindex];
11945 surface = surfaces + surfaceindex;
11946 texture = surface->texture;
11947 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11949 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11951 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11956 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11958 surfaceindex = surfacelist[surfacelistindex];
11959 surface = surfaces + surfaceindex;
11960 // check cull box first because it rejects more than any other check
11961 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11963 // skip transparent surfaces
11964 texture = surface->texture;
11965 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11967 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11969 numtriangles = surface->num_triangles;
11970 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11971 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11976 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11977 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, unsigned int decalsequence)
11979 int renderentityindex;
11980 float worldmins[3];
11981 float worldmaxs[3];
11982 entity_render_t *ent;
11984 if (!cl_decals_newsystem.integer)
11987 worldmins[0] = worldorigin[0] - worldsize;
11988 worldmins[1] = worldorigin[1] - worldsize;
11989 worldmins[2] = worldorigin[2] - worldsize;
11990 worldmaxs[0] = worldorigin[0] + worldsize;
11991 worldmaxs[1] = worldorigin[1] + worldsize;
11992 worldmaxs[2] = worldorigin[2] + worldsize;
11994 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11996 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11998 ent = r_refdef.scene.entities[renderentityindex];
11999 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
12002 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12006 typedef struct r_decalsystem_splatqueue_s
12008 vec3_t worldorigin;
12009 vec3_t worldnormal;
12013 unsigned int decalsequence;
12015 r_decalsystem_splatqueue_t;
12017 int r_decalsystem_numqueued = 0;
12018 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
12020 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)
12022 r_decalsystem_splatqueue_t *queue;
12024 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
12027 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
12028 VectorCopy(worldorigin, queue->worldorigin);
12029 VectorCopy(worldnormal, queue->worldnormal);
12030 Vector4Set(queue->color, r, g, b, a);
12031 Vector4Set(queue->tcrange, s1, t1, s2, t2);
12032 queue->worldsize = worldsize;
12033 queue->decalsequence = cl.decalsequence++;
12036 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
12039 r_decalsystem_splatqueue_t *queue;
12041 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
12042 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);
12043 r_decalsystem_numqueued = 0;
12046 extern cvar_t cl_decals_max;
12047 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12050 decalsystem_t *decalsystem = &ent->decalsystem;
12052 unsigned int killsequence;
12057 if (!decalsystem->numdecals)
12060 if (r_showsurfaces.integer)
12063 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12065 R_DecalSystem_Reset(decalsystem);
12069 killsequence = cl.decalsequence - bound(1, (unsigned int) cl_decals_max.integer, cl.decalsequence);
12070 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12072 if (decalsystem->lastupdatetime)
12073 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
12076 decalsystem->lastupdatetime = r_refdef.scene.time;
12077 numdecals = decalsystem->numdecals;
12079 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12081 if (decal->color4f[0][3])
12083 decal->lived += frametime;
12084 if (killsequence > decal->decalsequence || decal->lived >= lifetime)
12086 memset(decal, 0, sizeof(*decal));
12087 if (decalsystem->freedecal > i)
12088 decalsystem->freedecal = i;
12092 decal = decalsystem->decals;
12093 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
12096 // collapse the array by shuffling the tail decals into the gaps
12099 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
12100 decalsystem->freedecal++;
12101 if (decalsystem->freedecal == numdecals)
12103 decal[decalsystem->freedecal] = decal[--numdecals];
12106 decalsystem->numdecals = numdecals;
12108 if (numdecals <= 0)
12110 // if there are no decals left, reset decalsystem
12111 R_DecalSystem_Reset(decalsystem);
12115 extern skinframe_t *decalskinframe;
12116 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12119 decalsystem_t *decalsystem = &ent->decalsystem;
12128 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12131 numdecals = decalsystem->numdecals;
12135 if (r_showsurfaces.integer)
12138 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12140 R_DecalSystem_Reset(decalsystem);
12144 // if the model is static it doesn't matter what value we give for
12145 // wantnormals and wanttangents, so this logic uses only rules applicable
12146 // to a model, knowing that they are meaningless otherwise
12147 if (ent == r_refdef.scene.worldentity)
12148 RSurf_ActiveWorldEntity();
12150 RSurf_ActiveModelEntity(ent, false, false, false);
12152 decalsystem->lastupdatetime = r_refdef.scene.time;
12154 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12156 // update vertex positions for animated models
12157 v3f = decalsystem->vertex3f;
12158 c4f = decalsystem->color4f;
12159 t2f = decalsystem->texcoord2f;
12160 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12162 if (!decal->color4f[0][3])
12165 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12169 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
12172 // update color values for fading decals
12173 if (decal->lived >= cl_decals_time.value)
12174 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12178 c4f[ 0] = decal->color4f[0][0] * alpha;
12179 c4f[ 1] = decal->color4f[0][1] * alpha;
12180 c4f[ 2] = decal->color4f[0][2] * alpha;
12182 c4f[ 4] = decal->color4f[1][0] * alpha;
12183 c4f[ 5] = decal->color4f[1][1] * alpha;
12184 c4f[ 6] = decal->color4f[1][2] * alpha;
12186 c4f[ 8] = decal->color4f[2][0] * alpha;
12187 c4f[ 9] = decal->color4f[2][1] * alpha;
12188 c4f[10] = decal->color4f[2][2] * alpha;
12191 t2f[0] = decal->texcoord2f[0][0];
12192 t2f[1] = decal->texcoord2f[0][1];
12193 t2f[2] = decal->texcoord2f[1][0];
12194 t2f[3] = decal->texcoord2f[1][1];
12195 t2f[4] = decal->texcoord2f[2][0];
12196 t2f[5] = decal->texcoord2f[2][1];
12198 // update vertex positions for animated models
12199 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12201 e = rsurface.modelelement3i + 3*decal->triangleindex;
12202 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12203 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12204 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12208 VectorCopy(decal->vertex3f[0], v3f);
12209 VectorCopy(decal->vertex3f[1], v3f + 3);
12210 VectorCopy(decal->vertex3f[2], v3f + 6);
12213 if (r_refdef.fogenabled)
12215 alpha = RSurf_FogVertex(v3f);
12216 VectorScale(c4f, alpha, c4f);
12217 alpha = RSurf_FogVertex(v3f + 3);
12218 VectorScale(c4f + 4, alpha, c4f + 4);
12219 alpha = RSurf_FogVertex(v3f + 6);
12220 VectorScale(c4f + 8, alpha, c4f + 8);
12231 r_refdef.stats[r_stat_drawndecals] += numtris;
12233 // now render the decals all at once
12234 // (this assumes they all use one particle font texture!)
12235 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);
12236 // R_Mesh_ResetTextureState();
12237 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12238 GL_DepthMask(false);
12239 GL_DepthRange(0, 1);
12240 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12241 GL_DepthTest(true);
12242 GL_CullFace(GL_NONE);
12243 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12244 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12245 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12249 static void R_DrawModelDecals(void)
12253 // fade faster when there are too many decals
12254 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12255 for (i = 0;i < r_refdef.scene.numentities;i++)
12256 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12258 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12259 for (i = 0;i < r_refdef.scene.numentities;i++)
12260 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12261 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12263 R_DecalSystem_ApplySplatEntitiesQueue();
12265 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12266 for (i = 0;i < r_refdef.scene.numentities;i++)
12267 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12269 r_refdef.stats[r_stat_totaldecals] += numdecals;
12271 if (r_showsurfaces.integer)
12274 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12276 for (i = 0;i < r_refdef.scene.numentities;i++)
12278 if (!r_refdef.viewcache.entityvisible[i])
12280 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12281 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12285 extern cvar_t mod_collision_bih;
12286 static void R_DrawDebugModel(void)
12288 entity_render_t *ent = rsurface.entity;
12289 int i, j, flagsmask;
12290 const msurface_t *surface;
12291 dp_model_t *model = ent->model;
12293 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12296 if (r_showoverdraw.value > 0)
12298 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12299 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12300 R_SetupShader_Generic_NoTexture(false, false);
12301 GL_DepthTest(false);
12302 GL_DepthMask(false);
12303 GL_DepthRange(0, 1);
12304 GL_BlendFunc(GL_ONE, GL_ONE);
12305 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12307 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12309 rsurface.texture = R_GetCurrentTexture(surface->texture);
12310 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12312 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12313 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12314 if (!rsurface.texture->currentlayers->depthmask)
12315 GL_Color(c, 0, 0, 1.0f);
12316 else if (ent == r_refdef.scene.worldentity)
12317 GL_Color(c, c, c, 1.0f);
12319 GL_Color(0, c, 0, 1.0f);
12320 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12324 rsurface.texture = NULL;
12327 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12329 // R_Mesh_ResetTextureState();
12330 R_SetupShader_Generic_NoTexture(false, false);
12331 GL_DepthRange(0, 1);
12332 GL_DepthTest(!r_showdisabledepthtest.integer);
12333 GL_DepthMask(false);
12334 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12336 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12340 qboolean cullbox = false;
12341 const q3mbrush_t *brush;
12342 const bih_t *bih = &model->collision_bih;
12343 const bih_leaf_t *bihleaf;
12344 float vertex3f[3][3];
12345 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12346 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12348 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12350 switch (bihleaf->type)
12353 brush = model->brush.data_brushes + bihleaf->itemindex;
12354 if (brush->colbrushf && brush->colbrushf->numtriangles)
12356 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);
12357 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12358 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12361 case BIH_COLLISIONTRIANGLE:
12362 triangleindex = bihleaf->itemindex;
12363 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12364 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12365 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12366 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);
12367 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12368 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12370 case BIH_RENDERTRIANGLE:
12371 triangleindex = bihleaf->itemindex;
12372 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12373 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12374 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12375 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);
12376 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12377 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12383 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12386 if (r_showtris.integer && qglPolygonMode)
12388 if (r_showdisabledepthtest.integer)
12390 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12391 GL_DepthMask(false);
12395 GL_BlendFunc(GL_ONE, GL_ZERO);
12396 GL_DepthMask(true);
12398 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12399 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12401 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12403 rsurface.texture = R_GetCurrentTexture(surface->texture);
12404 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12406 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12407 if (!rsurface.texture->currentlayers->depthmask)
12408 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12409 else if (ent == r_refdef.scene.worldentity)
12410 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12412 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12413 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12417 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12418 rsurface.texture = NULL;
12421 if (r_shownormals.value != 0 && qglBegin)
12425 if (r_showdisabledepthtest.integer)
12427 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12428 GL_DepthMask(false);
12432 GL_BlendFunc(GL_ONE, GL_ZERO);
12433 GL_DepthMask(true);
12435 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12437 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12439 rsurface.texture = R_GetCurrentTexture(surface->texture);
12440 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12442 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12443 qglBegin(GL_LINES);
12444 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12446 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12448 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12449 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12450 qglVertex3f(v[0], v[1], v[2]);
12451 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12452 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12453 qglVertex3f(v[0], v[1], v[2]);
12456 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12458 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12460 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12461 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12462 qglVertex3f(v[0], v[1], v[2]);
12463 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12464 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12465 qglVertex3f(v[0], v[1], v[2]);
12468 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12470 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12472 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12473 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12474 qglVertex3f(v[0], v[1], v[2]);
12475 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12476 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12477 qglVertex3f(v[0], v[1], v[2]);
12480 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12482 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12484 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12485 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12486 qglVertex3f(v[0], v[1], v[2]);
12487 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12488 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12489 qglVertex3f(v[0], v[1], v[2]);
12496 rsurface.texture = NULL;
12501 int r_maxsurfacelist = 0;
12502 const msurface_t **r_surfacelist = NULL;
12503 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12505 int i, j, endj, flagsmask;
12506 dp_model_t *model = r_refdef.scene.worldmodel;
12507 msurface_t *surfaces;
12508 unsigned char *update;
12509 int numsurfacelist = 0;
12513 if (r_maxsurfacelist < model->num_surfaces)
12515 r_maxsurfacelist = model->num_surfaces;
12517 Mem_Free((msurface_t**)r_surfacelist);
12518 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12521 RSurf_ActiveWorldEntity();
12523 surfaces = model->data_surfaces;
12524 update = model->brushq1.lightmapupdateflags;
12526 // update light styles on this submodel
12527 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12529 model_brush_lightstyleinfo_t *style;
12530 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12532 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12534 int *list = style->surfacelist;
12535 style->value = r_refdef.scene.lightstylevalue[style->style];
12536 for (j = 0;j < style->numsurfaces;j++)
12537 update[list[j]] = true;
12542 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12546 R_DrawDebugModel();
12547 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12551 rsurface.lightmaptexture = NULL;
12552 rsurface.deluxemaptexture = NULL;
12553 rsurface.uselightmaptexture = false;
12554 rsurface.texture = NULL;
12555 rsurface.rtlight = NULL;
12556 numsurfacelist = 0;
12557 // add visible surfaces to draw list
12558 for (i = 0;i < model->nummodelsurfaces;i++)
12560 j = model->sortedmodelsurfaces[i];
12561 if (r_refdef.viewcache.world_surfacevisible[j])
12562 r_surfacelist[numsurfacelist++] = surfaces + j;
12564 // update lightmaps if needed
12565 if (model->brushq1.firstrender)
12567 model->brushq1.firstrender = false;
12568 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12570 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12574 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12575 if (r_refdef.viewcache.world_surfacevisible[j])
12577 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12579 // don't do anything if there were no surfaces
12580 if (!numsurfacelist)
12582 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12585 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12587 // add to stats if desired
12588 if (r_speeds.integer && !skysurfaces && !depthonly)
12590 r_refdef.stats[r_stat_world_surfaces] += numsurfacelist;
12591 for (j = 0;j < numsurfacelist;j++)
12592 r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles;
12595 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12598 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12600 int i, j, endj, flagsmask;
12601 dp_model_t *model = ent->model;
12602 msurface_t *surfaces;
12603 unsigned char *update;
12604 int numsurfacelist = 0;
12608 if (r_maxsurfacelist < model->num_surfaces)
12610 r_maxsurfacelist = model->num_surfaces;
12612 Mem_Free((msurface_t **)r_surfacelist);
12613 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12616 // if the model is static it doesn't matter what value we give for
12617 // wantnormals and wanttangents, so this logic uses only rules applicable
12618 // to a model, knowing that they are meaningless otherwise
12619 if (ent == r_refdef.scene.worldentity)
12620 RSurf_ActiveWorldEntity();
12621 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12622 RSurf_ActiveModelEntity(ent, false, false, false);
12624 RSurf_ActiveModelEntity(ent, true, true, true);
12625 else if (depthonly)
12627 switch (vid.renderpath)
12629 case RENDERPATH_GL20:
12630 case RENDERPATH_D3D9:
12631 case RENDERPATH_D3D10:
12632 case RENDERPATH_D3D11:
12633 case RENDERPATH_SOFT:
12634 case RENDERPATH_GLES2:
12635 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12637 case RENDERPATH_GL11:
12638 case RENDERPATH_GL13:
12639 case RENDERPATH_GLES1:
12640 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12646 switch (vid.renderpath)
12648 case RENDERPATH_GL20:
12649 case RENDERPATH_D3D9:
12650 case RENDERPATH_D3D10:
12651 case RENDERPATH_D3D11:
12652 case RENDERPATH_SOFT:
12653 case RENDERPATH_GLES2:
12654 RSurf_ActiveModelEntity(ent, true, true, false);
12656 case RENDERPATH_GL11:
12657 case RENDERPATH_GL13:
12658 case RENDERPATH_GLES1:
12659 RSurf_ActiveModelEntity(ent, true, false, false);
12664 surfaces = model->data_surfaces;
12665 update = model->brushq1.lightmapupdateflags;
12667 // update light styles
12668 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12670 model_brush_lightstyleinfo_t *style;
12671 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12673 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12675 int *list = style->surfacelist;
12676 style->value = r_refdef.scene.lightstylevalue[style->style];
12677 for (j = 0;j < style->numsurfaces;j++)
12678 update[list[j]] = true;
12683 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12687 R_DrawDebugModel();
12688 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12692 rsurface.lightmaptexture = NULL;
12693 rsurface.deluxemaptexture = NULL;
12694 rsurface.uselightmaptexture = false;
12695 rsurface.texture = NULL;
12696 rsurface.rtlight = NULL;
12697 numsurfacelist = 0;
12698 // add visible surfaces to draw list
12699 for (i = 0;i < model->nummodelsurfaces;i++)
12700 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12701 // don't do anything if there were no surfaces
12702 if (!numsurfacelist)
12704 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12707 // update lightmaps if needed
12711 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12716 R_BuildLightMap(ent, surfaces + j);
12721 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12723 // add to stats if desired
12724 if (r_speeds.integer && !skysurfaces && !depthonly)
12726 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12727 for (j = 0;j < numsurfacelist;j++)
12728 r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12731 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12734 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12736 static texture_t texture;
12737 static msurface_t surface;
12738 const msurface_t *surfacelist = &surface;
12740 // fake enough texture and surface state to render this geometry
12742 texture.update_lastrenderframe = -1; // regenerate this texture
12743 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12744 texture.basealpha = 1.0f;
12745 texture.currentskinframe = skinframe;
12746 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12747 texture.offsetmapping = OFFSETMAPPING_OFF;
12748 texture.offsetscale = 1;
12749 texture.specularscalemod = 1;
12750 texture.specularpowermod = 1;
12751 texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12752 // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12753 // JUST GREP FOR "specularscalemod = 1".
12755 surface.texture = &texture;
12756 surface.num_triangles = numtriangles;
12757 surface.num_firsttriangle = firsttriangle;
12758 surface.num_vertices = numvertices;
12759 surface.num_firstvertex = firstvertex;
12762 rsurface.texture = R_GetCurrentTexture(surface.texture);
12763 rsurface.lightmaptexture = NULL;
12764 rsurface.deluxemaptexture = NULL;
12765 rsurface.uselightmaptexture = false;
12766 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12769 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)
12771 static msurface_t surface;
12772 const msurface_t *surfacelist = &surface;
12774 // fake enough texture and surface state to render this geometry
12775 surface.texture = texture;
12776 surface.num_triangles = numtriangles;
12777 surface.num_firsttriangle = firsttriangle;
12778 surface.num_vertices = numvertices;
12779 surface.num_firstvertex = firstvertex;
12782 rsurface.texture = R_GetCurrentTexture(surface.texture);
12783 rsurface.lightmaptexture = NULL;
12784 rsurface.deluxemaptexture = NULL;
12785 rsurface.uselightmaptexture = false;
12786 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);