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;
38 // Enable NVIDIA High Performance Graphics while using Integrated Graphics.
42 __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
48 mempool_t *r_main_mempool;
49 rtexturepool_t *r_main_texturepool;
51 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
53 static qboolean r_loadnormalmap;
54 static qboolean r_loadgloss;
56 static qboolean r_loaddds;
57 static qboolean r_savedds;
58 static qboolean r_gpuskeletal;
65 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!"};
66 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!"};
67 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
68 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
69 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)"};
70 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
71 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"};
72 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"};
73 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"};
74 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"};
75 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"};
76 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"};
78 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
79 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"};
80 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
81 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)"};
82 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
84 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"};
85 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
86 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
87 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
88 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
89 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
90 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
91 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"};
92 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"};
93 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"};
94 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
95 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
96 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)"};
97 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
98 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
99 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"};
100 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"};
101 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
102 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"};
103 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"};
104 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"};
105 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
106 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
107 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
108 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
109 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
110 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
111 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
112 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)"};
113 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)"};
114 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
115 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
116 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
117 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
118 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
120 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
121 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
122 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
124 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
125 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
126 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
127 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."};
128 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
129 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
130 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
131 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."};
132 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
133 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
134 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
135 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."};
136 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
137 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"};
138 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"};
139 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
140 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
141 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
142 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
143 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
144 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"};
145 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
146 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
147 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
148 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
149 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
151 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
152 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
153 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
154 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
155 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
156 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
157 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
158 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
160 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)"};
161 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"};
163 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
164 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
165 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
167 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"};
168 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"};
169 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"};
170 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
171 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
172 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"};
173 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)"};
174 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)"};
175 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
177 cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
178 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)"};
179 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
180 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)"};
181 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
182 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)"};
183 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)"};
184 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
185 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"};
186 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."};
187 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
188 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)"};
189 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)"};
190 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)"};
191 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)"};
192 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)"};
193 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)"};
194 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)"};
195 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)"};
197 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)"};
198 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)"};
199 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
200 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"};
201 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
202 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
203 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
204 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"};
205 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"};
206 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)"};
208 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
209 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
210 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
211 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
213 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
214 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
216 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
217 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
218 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
219 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
220 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
221 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
223 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
224 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
225 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
226 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
227 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
228 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
229 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
230 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
231 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
232 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
234 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"};
236 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"};
238 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
240 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
242 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)"};
243 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)"};
244 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
245 cvar_t r_batch_dynamicbuffer = {CVAR_SAVE, "r_batch_dynamicbuffer", "0", "use vertex/index buffers for drawing dynamic and copytriangles batches"};
247 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
248 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"};
250 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."};
252 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)"};
253 cvar_t r_buffermegs[R_BUFFERDATA_COUNT] =
255 {CVAR_SAVE, "r_buffermegs_vertex", "4", "vertex buffer size for one frame"},
256 {CVAR_SAVE, "r_buffermegs_index16", "1", "index buffer size for one frame (16bit indices)"},
257 {CVAR_SAVE, "r_buffermegs_index32", "1", "index buffer size for one frame (32bit indices)"},
258 {CVAR_SAVE, "r_buffermegs_uniform", "0.25", "uniform buffer size for one frame"},
261 extern cvar_t v_glslgamma;
262 extern cvar_t v_glslgamma_2d;
264 extern qboolean v_flipped_state;
266 r_framebufferstate_t r_fb;
268 /// shadow volume bsp struct with automatically growing nodes buffer
271 int r_uniformbufferalignment = 32; // dynamically updated to match GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
273 rtexture_t *r_texture_blanknormalmap;
274 rtexture_t *r_texture_white;
275 rtexture_t *r_texture_grey128;
276 rtexture_t *r_texture_black;
277 rtexture_t *r_texture_notexture;
278 rtexture_t *r_texture_whitecube;
279 rtexture_t *r_texture_normalizationcube;
280 rtexture_t *r_texture_fogattenuation;
281 rtexture_t *r_texture_fogheighttexture;
282 rtexture_t *r_texture_gammaramps;
283 unsigned int r_texture_gammaramps_serial;
284 //rtexture_t *r_texture_fogintensity;
285 rtexture_t *r_texture_reflectcube;
287 // TODO: hash lookups?
288 typedef struct cubemapinfo_s
295 int r_texture_numcubemaps;
296 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
298 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
299 unsigned int r_numqueries;
300 unsigned int r_maxqueries;
302 typedef struct r_qwskincache_s
304 char name[MAX_QPATH];
305 skinframe_t *skinframe;
309 static r_qwskincache_t *r_qwskincache;
310 static int r_qwskincache_size;
312 /// vertex coordinates for a quad that covers the screen exactly
313 extern const float r_screenvertex3f[12];
314 extern const float r_d3dscreenvertex3f[12];
315 const float r_screenvertex3f[12] =
322 const float r_d3dscreenvertex3f[12] =
330 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
333 for (i = 0;i < verts;i++)
344 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
347 for (i = 0;i < verts;i++)
357 // FIXME: move this to client?
360 if (gamemode == GAME_NEHAHRA)
362 Cvar_Set("gl_fogenable", "0");
363 Cvar_Set("gl_fogdensity", "0.2");
364 Cvar_Set("gl_fogred", "0.3");
365 Cvar_Set("gl_foggreen", "0.3");
366 Cvar_Set("gl_fogblue", "0.3");
368 r_refdef.fog_density = 0;
369 r_refdef.fog_red = 0;
370 r_refdef.fog_green = 0;
371 r_refdef.fog_blue = 0;
372 r_refdef.fog_alpha = 1;
373 r_refdef.fog_start = 0;
374 r_refdef.fog_end = 16384;
375 r_refdef.fog_height = 1<<30;
376 r_refdef.fog_fadedepth = 128;
377 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
380 static void R_BuildBlankTextures(void)
382 unsigned char data[4];
383 data[2] = 128; // normal X
384 data[1] = 128; // normal Y
385 data[0] = 255; // normal Z
386 data[3] = 255; // height
387 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
392 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
397 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
402 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
405 static void R_BuildNoTexture(void)
408 unsigned char pix[16][16][4];
409 // this makes a light grey/dark grey checkerboard texture
410 for (y = 0;y < 16;y++)
412 for (x = 0;x < 16;x++)
414 if ((y < 8) ^ (x < 8))
430 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
433 static void R_BuildWhiteCube(void)
435 unsigned char data[6*1*1*4];
436 memset(data, 255, sizeof(data));
437 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
440 static void R_BuildNormalizationCube(void)
444 vec_t s, t, intensity;
447 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
448 for (side = 0;side < 6;side++)
450 for (y = 0;y < NORMSIZE;y++)
452 for (x = 0;x < NORMSIZE;x++)
454 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
455 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
490 intensity = 127.0f / sqrt(DotProduct(v, v));
491 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
492 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
493 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
494 data[((side*64+y)*64+x)*4+3] = 255;
498 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
502 static void R_BuildFogTexture(void)
506 unsigned char data1[FOGWIDTH][4];
507 //unsigned char data2[FOGWIDTH][4];
510 r_refdef.fogmasktable_start = r_refdef.fog_start;
511 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
512 r_refdef.fogmasktable_range = r_refdef.fogrange;
513 r_refdef.fogmasktable_density = r_refdef.fog_density;
515 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
516 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
518 d = (x * r - r_refdef.fogmasktable_start);
519 if(developer_extra.integer)
520 Con_DPrintf("%f ", d);
522 if (r_fog_exp2.integer)
523 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
525 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
526 if(developer_extra.integer)
527 Con_DPrintf(" : %f ", alpha);
528 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
529 if(developer_extra.integer)
530 Con_DPrintf(" = %f\n", alpha);
531 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
534 for (x = 0;x < FOGWIDTH;x++)
536 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
541 //data2[x][0] = 255 - b;
542 //data2[x][1] = 255 - b;
543 //data2[x][2] = 255 - b;
546 if (r_texture_fogattenuation)
548 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
549 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
553 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
554 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
558 static void R_BuildFogHeightTexture(void)
560 unsigned char *inpixels;
568 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
569 if (r_refdef.fogheighttexturename[0])
570 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
573 r_refdef.fog_height_tablesize = 0;
574 if (r_texture_fogheighttexture)
575 R_FreeTexture(r_texture_fogheighttexture);
576 r_texture_fogheighttexture = NULL;
577 if (r_refdef.fog_height_table2d)
578 Mem_Free(r_refdef.fog_height_table2d);
579 r_refdef.fog_height_table2d = NULL;
580 if (r_refdef.fog_height_table1d)
581 Mem_Free(r_refdef.fog_height_table1d);
582 r_refdef.fog_height_table1d = NULL;
586 r_refdef.fog_height_tablesize = size;
587 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
588 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
589 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
591 // LordHavoc: now the magic - what is that table2d for? it is a cooked
592 // average fog color table accounting for every fog layer between a point
593 // and the camera. (Note: attenuation is handled separately!)
594 for (y = 0;y < size;y++)
596 for (x = 0;x < size;x++)
602 for (j = x;j <= y;j++)
604 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
610 for (j = x;j >= y;j--)
612 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
617 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
618 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
619 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
620 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
623 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
626 //=======================================================================================================================================================
628 static const char *builtinshaderstrings[] =
630 #include "shader_glsl.h"
634 const char *builtinhlslshaderstrings[] =
636 #include "shader_hlsl.h"
640 char *glslshaderstring = NULL;
641 char *hlslshaderstring = NULL;
643 //=======================================================================================================================================================
645 typedef struct shaderpermutationinfo_s
650 shaderpermutationinfo_t;
652 typedef struct shadermodeinfo_s
654 const char *filename;
660 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
661 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
663 {"#define USEDIFFUSE\n", " diffuse"},
664 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
665 {"#define USEVIEWTINT\n", " viewtint"},
666 {"#define USECOLORMAPPING\n", " colormapping"},
667 {"#define USESATURATION\n", " saturation"},
668 {"#define USEFOGINSIDE\n", " foginside"},
669 {"#define USEFOGOUTSIDE\n", " fogoutside"},
670 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
671 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
672 {"#define USEGAMMARAMPS\n", " gammaramps"},
673 {"#define USECUBEFILTER\n", " cubefilter"},
674 {"#define USEGLOW\n", " glow"},
675 {"#define USEBLOOM\n", " bloom"},
676 {"#define USESPECULAR\n", " specular"},
677 {"#define USEPOSTPROCESSING\n", " postprocessing"},
678 {"#define USEREFLECTION\n", " reflection"},
679 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
680 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
681 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
682 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
683 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
684 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
685 {"#define USEALPHAKILL\n", " alphakill"},
686 {"#define USEREFLECTCUBE\n", " reflectcube"},
687 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
688 {"#define USEBOUNCEGRID\n", " bouncegrid"},
689 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
690 {"#define USETRIPPY\n", " trippy"},
691 {"#define USEDEPTHRGB\n", " depthrgb"},
692 {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
693 {"#define USESKELETAL\n", " skeletal"},
694 {"#define USEOCCLUDE\n", " occlude"}
697 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
698 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
700 {"glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
701 {"glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
702 {"glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
703 {"glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
704 {"glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
705 {"glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
706 {"glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
707 {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
708 {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
709 {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
710 {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
711 {"glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
712 {"glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
713 {"glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
714 {"glsl/default.glsl", "#define MODE_WATER\n", " water"},
715 {"glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
716 {"glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
719 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
721 {"hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
722 {"hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
723 {"hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
724 {"hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
725 {"hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
726 {"hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
727 {"hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
728 {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
729 {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
730 {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
731 {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
732 {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
733 {"hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
734 {"hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
735 {"hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
736 {"hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
737 {"hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
740 struct r_glsl_permutation_s;
741 typedef struct r_glsl_permutation_s
744 struct r_glsl_permutation_s *hashnext;
746 unsigned int permutation;
748 /// indicates if we have tried compiling this permutation already
750 /// 0 if compilation failed
752 // texture units assigned to each detected uniform
753 int tex_Texture_First;
754 int tex_Texture_Second;
755 int tex_Texture_GammaRamps;
756 int tex_Texture_Normal;
757 int tex_Texture_Color;
758 int tex_Texture_Gloss;
759 int tex_Texture_Glow;
760 int tex_Texture_SecondaryNormal;
761 int tex_Texture_SecondaryColor;
762 int tex_Texture_SecondaryGloss;
763 int tex_Texture_SecondaryGlow;
764 int tex_Texture_Pants;
765 int tex_Texture_Shirt;
766 int tex_Texture_FogHeightTexture;
767 int tex_Texture_FogMask;
768 int tex_Texture_Lightmap;
769 int tex_Texture_Deluxemap;
770 int tex_Texture_Attenuation;
771 int tex_Texture_Cube;
772 int tex_Texture_Refraction;
773 int tex_Texture_Reflection;
774 int tex_Texture_ShadowMap2D;
775 int tex_Texture_CubeProjection;
776 int tex_Texture_ScreenNormalMap;
777 int tex_Texture_ScreenDiffuse;
778 int tex_Texture_ScreenSpecular;
779 int tex_Texture_ReflectMask;
780 int tex_Texture_ReflectCube;
781 int tex_Texture_BounceGrid;
782 /// locations of detected uniforms in program object, or -1 if not found
783 int loc_Texture_First;
784 int loc_Texture_Second;
785 int loc_Texture_GammaRamps;
786 int loc_Texture_Normal;
787 int loc_Texture_Color;
788 int loc_Texture_Gloss;
789 int loc_Texture_Glow;
790 int loc_Texture_SecondaryNormal;
791 int loc_Texture_SecondaryColor;
792 int loc_Texture_SecondaryGloss;
793 int loc_Texture_SecondaryGlow;
794 int loc_Texture_Pants;
795 int loc_Texture_Shirt;
796 int loc_Texture_FogHeightTexture;
797 int loc_Texture_FogMask;
798 int loc_Texture_Lightmap;
799 int loc_Texture_Deluxemap;
800 int loc_Texture_Attenuation;
801 int loc_Texture_Cube;
802 int loc_Texture_Refraction;
803 int loc_Texture_Reflection;
804 int loc_Texture_ShadowMap2D;
805 int loc_Texture_CubeProjection;
806 int loc_Texture_ScreenNormalMap;
807 int loc_Texture_ScreenDiffuse;
808 int loc_Texture_ScreenSpecular;
809 int loc_Texture_ReflectMask;
810 int loc_Texture_ReflectCube;
811 int loc_Texture_BounceGrid;
813 int loc_BloomBlur_Parameters;
815 int loc_Color_Ambient;
816 int loc_Color_Diffuse;
817 int loc_Color_Specular;
821 int loc_DeferredColor_Ambient;
822 int loc_DeferredColor_Diffuse;
823 int loc_DeferredColor_Specular;
824 int loc_DeferredMod_Diffuse;
825 int loc_DeferredMod_Specular;
826 int loc_DistortScaleRefractReflect;
829 int loc_FogHeightFade;
831 int loc_FogPlaneViewDist;
832 int loc_FogRangeRecip;
835 int loc_LightPosition;
836 int loc_OffsetMapping_ScaleSteps;
837 int loc_OffsetMapping_LodDistance;
838 int loc_OffsetMapping_Bias;
840 int loc_ReflectColor;
841 int loc_ReflectFactor;
842 int loc_ReflectOffset;
843 int loc_RefractColor;
845 int loc_ScreenCenterRefractReflect;
846 int loc_ScreenScaleRefractReflect;
847 int loc_ScreenToDepth;
848 int loc_ShadowMap_Parameters;
849 int loc_ShadowMap_TextureScale;
850 int loc_SpecularPower;
851 int loc_Skeletal_Transform12;
856 int loc_ViewTintColor;
858 int loc_ModelToLight;
860 int loc_BackgroundTexMatrix;
861 int loc_ModelViewProjectionMatrix;
862 int loc_ModelViewMatrix;
863 int loc_PixelToScreenTexCoord;
864 int loc_ModelToReflectCube;
865 int loc_ShadowMapMatrix;
866 int loc_BloomColorSubtract;
867 int loc_NormalmapScrollBlend;
868 int loc_BounceGridMatrix;
869 int loc_BounceGridIntensity;
870 /// uniform block bindings
871 int ubibind_Skeletal_Transform12_UniformBlock;
872 /// uniform block indices
873 int ubiloc_Skeletal_Transform12_UniformBlock;
875 r_glsl_permutation_t;
877 #define SHADERPERMUTATION_HASHSIZE 256
880 // non-degradable "lightweight" shader parameters to keep the permutations simpler
881 // these can NOT degrade! only use for simple stuff
884 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
885 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
886 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
887 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
888 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
889 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
890 SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
891 SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7, ///< LOD for offsetmapping
892 SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
893 SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
894 SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
895 SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
896 SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
897 SHADERSTATICPARM_FXAA = 13 ///< fast approximate anti aliasing
899 #define SHADERSTATICPARMS_COUNT 14
901 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
902 static int shaderstaticparms_count = 0;
904 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
905 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
907 extern qboolean r_shadow_shadowmapsampler;
908 extern int r_shadow_shadowmappcf;
909 qboolean R_CompileShader_CheckStaticParms(void)
911 static int r_compileshader_staticparms_save[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5];
912 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
913 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
916 if (r_glsl_saturation_redcompensate.integer)
917 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
918 if (r_glsl_vertextextureblend_usebothalphas.integer)
919 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
920 if (r_shadow_glossexact.integer)
921 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
922 if (r_glsl_postprocess.integer)
924 if (r_glsl_postprocess_uservec1_enable.integer)
925 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
926 if (r_glsl_postprocess_uservec2_enable.integer)
927 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
928 if (r_glsl_postprocess_uservec3_enable.integer)
929 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
930 if (r_glsl_postprocess_uservec4_enable.integer)
931 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
934 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_FXAA);
935 if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
936 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
938 if (r_shadow_shadowmapsampler)
939 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
940 if (r_shadow_shadowmappcf > 1)
941 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
942 else if (r_shadow_shadowmappcf)
943 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
944 if (r_celshading.integer)
945 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
946 if (r_celoutlines.integer)
947 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
949 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
952 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
953 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
954 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
956 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
957 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
959 shaderstaticparms_count = 0;
962 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
963 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
964 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
965 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
966 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
967 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
968 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
969 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
970 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
971 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
972 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
973 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
974 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
975 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_FXAA, "USEFXAA");
978 /// information about each possible shader permutation
979 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
980 /// currently selected permutation
981 r_glsl_permutation_t *r_glsl_permutation;
982 /// storage for permutations linked in the hash table
983 memexpandablearray_t r_glsl_permutationarray;
985 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
987 //unsigned int hashdepth = 0;
988 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
989 r_glsl_permutation_t *p;
990 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
992 if (p->mode == mode && p->permutation == permutation)
994 //if (hashdepth > 10)
995 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1000 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1002 p->permutation = permutation;
1003 p->hashnext = r_glsl_permutationhash[mode][hashindex];
1004 r_glsl_permutationhash[mode][hashindex] = p;
1005 //if (hashdepth > 10)
1006 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1010 static char *R_ShaderStrCat(const char **strings)
1013 const char **p = strings;
1016 for (p = strings;(t = *p);p++)
1019 s = string = (char *)Mem_Alloc(r_main_mempool, len);
1021 for (p = strings;(t = *p);p++)
1031 static char *R_GetShaderText(const char *filename, qboolean printfromdisknotice, qboolean builtinonly)
1034 if (!filename || !filename[0])
1036 // LordHavoc: note that FS_LoadFile appends a 0 byte to make it a valid string, so does R_ShaderStrCat
1037 if (!strcmp(filename, "glsl/default.glsl"))
1040 return R_ShaderStrCat(builtinshaderstrings);
1041 if (!glslshaderstring)
1043 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1044 if (glslshaderstring)
1045 Con_DPrintf("Loading shaders from file %s...\n", filename);
1047 glslshaderstring = R_ShaderStrCat(builtinshaderstrings);
1049 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
1050 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
1051 return shaderstring;
1053 if (!strcmp(filename, "hlsl/default.hlsl"))
1056 return R_ShaderStrCat(builtinhlslshaderstrings);
1057 if (!hlslshaderstring)
1059 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1060 if (hlslshaderstring)
1061 Con_DPrintf("Loading shaders from file %s...\n", filename);
1063 hlslshaderstring = R_ShaderStrCat(builtinhlslshaderstrings);
1065 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1066 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1067 return shaderstring;
1069 // we don't have builtin strings for any other files
1072 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1075 if (printfromdisknotice)
1076 Con_DPrintf("from disk %s... ", filename);
1077 return shaderstring;
1079 return shaderstring;
1082 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1087 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1089 char permutationname[256];
1090 int vertstrings_count = 0;
1091 int geomstrings_count = 0;
1092 int fragstrings_count = 0;
1093 const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1094 const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1095 const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1102 permutationname[0] = 0;
1103 sourcestring = R_GetShaderText(modeinfo->filename, true, false);
1105 strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1107 // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1108 if(vid.support.glshaderversion >= 140)
1110 vertstrings_list[vertstrings_count++] = "#version 140\n";
1111 geomstrings_list[geomstrings_count++] = "#version 140\n";
1112 fragstrings_list[fragstrings_count++] = "#version 140\n";
1113 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1114 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1115 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1117 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1118 else if(vid.support.glshaderversion >= 130)
1120 vertstrings_list[vertstrings_count++] = "#version 130\n";
1121 geomstrings_list[geomstrings_count++] = "#version 130\n";
1122 fragstrings_list[fragstrings_count++] = "#version 130\n";
1123 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1124 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1125 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1128 // the first pretext is which type of shader to compile as
1129 // (later these will all be bound together as a program object)
1130 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1131 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1132 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1134 // the second pretext is the mode (for example a light source)
1135 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1136 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1137 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1138 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1140 // now add all the permutation pretexts
1141 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1143 if (permutation & (1<<i))
1145 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1146 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1147 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1148 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1152 // keep line numbers correct
1153 vertstrings_list[vertstrings_count++] = "\n";
1154 geomstrings_list[geomstrings_count++] = "\n";
1155 fragstrings_list[fragstrings_count++] = "\n";
1160 R_CompileShader_AddStaticParms(mode, permutation);
1161 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1162 vertstrings_count += shaderstaticparms_count;
1163 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1164 geomstrings_count += shaderstaticparms_count;
1165 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1166 fragstrings_count += shaderstaticparms_count;
1168 // now append the shader text itself
1169 vertstrings_list[vertstrings_count++] = sourcestring;
1170 geomstrings_list[geomstrings_count++] = sourcestring;
1171 fragstrings_list[fragstrings_count++] = sourcestring;
1173 // compile the shader program
1174 if (vertstrings_count + geomstrings_count + fragstrings_count)
1175 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1179 qglUseProgram(p->program);CHECKGLERROR
1180 // look up all the uniform variable names we care about, so we don't
1181 // have to look them up every time we set them
1186 GLint activeuniformindex = 0;
1187 GLint numactiveuniforms = 0;
1188 char uniformname[128];
1189 GLsizei uniformnamelength = 0;
1190 GLint uniformsize = 0;
1191 GLenum uniformtype = 0;
1192 memset(uniformname, 0, sizeof(uniformname));
1193 qglGetProgramiv(p->program, GL_ACTIVE_UNIFORMS, &numactiveuniforms);
1194 Con_Printf("Shader has %i uniforms\n", numactiveuniforms);
1195 for (activeuniformindex = 0;activeuniformindex < numactiveuniforms;activeuniformindex++)
1197 qglGetActiveUniform(p->program, activeuniformindex, sizeof(uniformname) - 1, &uniformnamelength, &uniformsize, &uniformtype, uniformname);
1198 Con_Printf("Uniform %i name \"%s\" size %i type %i\n", (int)activeuniformindex, uniformname, (int)uniformsize, (int)uniformtype);
1203 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1204 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1205 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1206 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1207 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1208 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1209 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1210 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1211 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1212 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1213 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1214 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1215 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1216 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1217 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1218 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1219 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1220 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1221 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1222 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1223 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1224 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1225 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1226 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1227 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1228 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1229 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1230 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1231 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1232 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1233 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1234 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1235 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1236 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1237 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1238 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1239 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1240 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1241 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1242 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1243 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1244 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1245 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1246 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1247 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1248 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1249 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1250 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1251 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1252 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1253 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1254 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1255 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1256 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1257 p->loc_OffsetMapping_LodDistance = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1258 p->loc_OffsetMapping_Bias = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1259 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1260 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1261 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1262 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1263 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1264 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1265 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1266 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1267 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1268 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1269 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1270 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1271 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1272 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1273 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1274 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1275 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1276 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1277 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1278 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1279 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1280 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1281 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1282 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1283 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1284 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1285 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1286 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1287 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1288 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1289 // initialize the samplers to refer to the texture units we use
1290 p->tex_Texture_First = -1;
1291 p->tex_Texture_Second = -1;
1292 p->tex_Texture_GammaRamps = -1;
1293 p->tex_Texture_Normal = -1;
1294 p->tex_Texture_Color = -1;
1295 p->tex_Texture_Gloss = -1;
1296 p->tex_Texture_Glow = -1;
1297 p->tex_Texture_SecondaryNormal = -1;
1298 p->tex_Texture_SecondaryColor = -1;
1299 p->tex_Texture_SecondaryGloss = -1;
1300 p->tex_Texture_SecondaryGlow = -1;
1301 p->tex_Texture_Pants = -1;
1302 p->tex_Texture_Shirt = -1;
1303 p->tex_Texture_FogHeightTexture = -1;
1304 p->tex_Texture_FogMask = -1;
1305 p->tex_Texture_Lightmap = -1;
1306 p->tex_Texture_Deluxemap = -1;
1307 p->tex_Texture_Attenuation = -1;
1308 p->tex_Texture_Cube = -1;
1309 p->tex_Texture_Refraction = -1;
1310 p->tex_Texture_Reflection = -1;
1311 p->tex_Texture_ShadowMap2D = -1;
1312 p->tex_Texture_CubeProjection = -1;
1313 p->tex_Texture_ScreenNormalMap = -1;
1314 p->tex_Texture_ScreenDiffuse = -1;
1315 p->tex_Texture_ScreenSpecular = -1;
1316 p->tex_Texture_ReflectMask = -1;
1317 p->tex_Texture_ReflectCube = -1;
1318 p->tex_Texture_BounceGrid = -1;
1319 // bind the texture samplers in use
1321 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1322 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1323 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1324 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1325 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1326 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1327 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1328 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1329 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1330 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1331 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1332 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1333 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1334 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1335 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1336 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1337 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1338 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1339 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1340 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1341 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1342 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1343 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1344 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1345 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1346 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1347 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1348 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1349 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1350 // get the uniform block indices so we can bind them
1351 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1352 if (vid.support.arb_uniform_buffer_object)
1353 p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1356 p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1357 // clear the uniform block bindings
1358 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1359 // bind the uniform blocks in use
1361 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1362 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1364 // we're done compiling and setting up the shader, at least until it is used
1366 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1369 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1373 Mem_Free(sourcestring);
1376 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1378 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1379 if (r_glsl_permutation != perm)
1381 r_glsl_permutation = perm;
1382 if (!r_glsl_permutation->program)
1384 if (!r_glsl_permutation->compiled)
1386 Con_DPrintf("Compiling shader mode %u permutation %u\n", mode, permutation);
1387 R_GLSL_CompilePermutation(perm, mode, permutation);
1389 if (!r_glsl_permutation->program)
1391 // remove features until we find a valid permutation
1393 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1395 // reduce i more quickly whenever it would not remove any bits
1396 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1397 if (!(permutation & j))
1400 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1401 if (!r_glsl_permutation->compiled)
1402 R_GLSL_CompilePermutation(perm, mode, permutation);
1403 if (r_glsl_permutation->program)
1406 if (i >= SHADERPERMUTATION_COUNT)
1408 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1409 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1410 qglUseProgram(0);CHECKGLERROR
1411 return; // no bit left to clear, entire mode is broken
1416 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1418 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1419 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1420 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1428 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1429 extern D3DCAPS9 vid_d3d9caps;
1432 struct r_hlsl_permutation_s;
1433 typedef struct r_hlsl_permutation_s
1435 /// hash lookup data
1436 struct r_hlsl_permutation_s *hashnext;
1438 unsigned int permutation;
1440 /// indicates if we have tried compiling this permutation already
1442 /// NULL if compilation failed
1443 IDirect3DVertexShader9 *vertexshader;
1444 IDirect3DPixelShader9 *pixelshader;
1446 r_hlsl_permutation_t;
1448 typedef enum D3DVSREGISTER_e
1450 D3DVSREGISTER_TexMatrix = 0, // float4x4
1451 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1452 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1453 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1454 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1455 D3DVSREGISTER_ModelToLight = 20, // float4x4
1456 D3DVSREGISTER_EyePosition = 24,
1457 D3DVSREGISTER_FogPlane = 25,
1458 D3DVSREGISTER_LightDir = 26,
1459 D3DVSREGISTER_LightPosition = 27,
1463 typedef enum D3DPSREGISTER_e
1465 D3DPSREGISTER_Alpha = 0,
1466 D3DPSREGISTER_BloomBlur_Parameters = 1,
1467 D3DPSREGISTER_ClientTime = 2,
1468 D3DPSREGISTER_Color_Ambient = 3,
1469 D3DPSREGISTER_Color_Diffuse = 4,
1470 D3DPSREGISTER_Color_Specular = 5,
1471 D3DPSREGISTER_Color_Glow = 6,
1472 D3DPSREGISTER_Color_Pants = 7,
1473 D3DPSREGISTER_Color_Shirt = 8,
1474 D3DPSREGISTER_DeferredColor_Ambient = 9,
1475 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1476 D3DPSREGISTER_DeferredColor_Specular = 11,
1477 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1478 D3DPSREGISTER_DeferredMod_Specular = 13,
1479 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1480 D3DPSREGISTER_EyePosition = 15, // unused
1481 D3DPSREGISTER_FogColor = 16,
1482 D3DPSREGISTER_FogHeightFade = 17,
1483 D3DPSREGISTER_FogPlane = 18,
1484 D3DPSREGISTER_FogPlaneViewDist = 19,
1485 D3DPSREGISTER_FogRangeRecip = 20,
1486 D3DPSREGISTER_LightColor = 21,
1487 D3DPSREGISTER_LightDir = 22, // unused
1488 D3DPSREGISTER_LightPosition = 23,
1489 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1490 D3DPSREGISTER_PixelSize = 25,
1491 D3DPSREGISTER_ReflectColor = 26,
1492 D3DPSREGISTER_ReflectFactor = 27,
1493 D3DPSREGISTER_ReflectOffset = 28,
1494 D3DPSREGISTER_RefractColor = 29,
1495 D3DPSREGISTER_Saturation = 30,
1496 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1497 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1498 D3DPSREGISTER_ScreenToDepth = 33,
1499 D3DPSREGISTER_ShadowMap_Parameters = 34,
1500 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1501 D3DPSREGISTER_SpecularPower = 36,
1502 D3DPSREGISTER_UserVec1 = 37,
1503 D3DPSREGISTER_UserVec2 = 38,
1504 D3DPSREGISTER_UserVec3 = 39,
1505 D3DPSREGISTER_UserVec4 = 40,
1506 D3DPSREGISTER_ViewTintColor = 41,
1507 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1508 D3DPSREGISTER_BloomColorSubtract = 43,
1509 D3DPSREGISTER_ViewToLight = 44, // float4x4
1510 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1511 D3DPSREGISTER_NormalmapScrollBlend = 52,
1512 D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1513 D3DPSREGISTER_OffsetMapping_Bias = 54,
1518 /// information about each possible shader permutation
1519 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1520 /// currently selected permutation
1521 r_hlsl_permutation_t *r_hlsl_permutation;
1522 /// storage for permutations linked in the hash table
1523 memexpandablearray_t r_hlsl_permutationarray;
1525 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1527 //unsigned int hashdepth = 0;
1528 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1529 r_hlsl_permutation_t *p;
1530 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1532 if (p->mode == mode && p->permutation == permutation)
1534 //if (hashdepth > 10)
1535 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1540 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1542 p->permutation = permutation;
1543 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1544 r_hlsl_permutationhash[mode][hashindex] = p;
1545 //if (hashdepth > 10)
1546 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1551 //#include <d3dx9shader.h>
1552 //#include <d3dx9mesh.h>
1554 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1556 DWORD *vsbin = NULL;
1557 DWORD *psbin = NULL;
1558 fs_offset_t vsbinsize;
1559 fs_offset_t psbinsize;
1560 // IDirect3DVertexShader9 *vs = NULL;
1561 // IDirect3DPixelShader9 *ps = NULL;
1562 ID3DXBuffer *vslog = NULL;
1563 ID3DXBuffer *vsbuffer = NULL;
1564 ID3DXConstantTable *vsconstanttable = NULL;
1565 ID3DXBuffer *pslog = NULL;
1566 ID3DXBuffer *psbuffer = NULL;
1567 ID3DXConstantTable *psconstanttable = NULL;
1570 char temp[MAX_INPUTLINE];
1571 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1573 qboolean debugshader = gl_paranoid.integer != 0;
1574 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1575 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1578 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1579 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1581 if ((!vsbin && vertstring) || (!psbin && fragstring))
1583 const char* dllnames_d3dx9 [] =
1607 dllhandle_t d3dx9_dll = NULL;
1608 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1609 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1610 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1611 dllfunction_t d3dx9_dllfuncs[] =
1613 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1614 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1615 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1618 // 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...
1619 #ifndef ID3DXBuffer_GetBufferPointer
1620 #if !defined(__cplusplus) || defined(CINTERFACE)
1621 #define ID3DXBuffer_GetBufferPointer(p) (p)->lpVtbl->GetBufferPointer(p)
1622 #define ID3DXBuffer_GetBufferSize(p) (p)->lpVtbl->GetBufferSize(p)
1623 #define ID3DXBuffer_Release(p) (p)->lpVtbl->Release(p)
1625 #define ID3DXBuffer_GetBufferPointer(p) (p)->GetBufferPointer()
1626 #define ID3DXBuffer_GetBufferSize(p) (p)->GetBufferSize()
1627 #define ID3DXBuffer_Release(p) (p)->Release()
1630 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1632 DWORD shaderflags = 0;
1634 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1635 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1636 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1637 if (vertstring && vertstring[0])
1641 FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1642 vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1645 vsresult = qD3DXCompileShader(vertstring, (unsigned int)strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1648 vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1649 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1650 memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1651 ID3DXBuffer_Release(vsbuffer);
1655 strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1656 Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1657 ID3DXBuffer_Release(vslog);
1660 if (fragstring && fragstring[0])
1664 FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1665 psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1668 psresult = qD3DXCompileShader(fragstring, (unsigned int)strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1671 psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1672 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1673 memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1674 ID3DXBuffer_Release(psbuffer);
1678 strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1679 Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1680 ID3DXBuffer_Release(pslog);
1683 Sys_UnloadLibrary(&d3dx9_dll);
1686 Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1690 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1691 if (FAILED(vsresult))
1692 Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1693 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1694 if (FAILED(psresult))
1695 Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1697 // free the shader data
1698 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1699 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1702 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1705 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1706 int vertstring_length = 0;
1707 int geomstring_length = 0;
1708 int fragstring_length = 0;
1711 char *vertstring, *geomstring, *fragstring;
1712 char permutationname[256];
1713 char cachename[256];
1714 int vertstrings_count = 0;
1715 int geomstrings_count = 0;
1716 int fragstrings_count = 0;
1717 const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1718 const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1719 const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1724 p->vertexshader = NULL;
1725 p->pixelshader = NULL;
1727 permutationname[0] = 0;
1729 sourcestring = R_GetShaderText(modeinfo->filename, true, false);
1731 strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1732 strlcat(cachename, "hlsl/", sizeof(cachename));
1734 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1735 vertstrings_count = 0;
1736 geomstrings_count = 0;
1737 fragstrings_count = 0;
1738 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1739 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1740 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1742 // the first pretext is which type of shader to compile as
1743 // (later these will all be bound together as a program object)
1744 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1745 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1746 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1748 // the second pretext is the mode (for example a light source)
1749 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1750 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1751 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1752 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1753 strlcat(cachename, modeinfo->name, sizeof(cachename));
1755 // now add all the permutation pretexts
1756 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1758 if (permutation & (1<<i))
1760 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1761 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1762 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1763 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1764 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1768 // keep line numbers correct
1769 vertstrings_list[vertstrings_count++] = "\n";
1770 geomstrings_list[geomstrings_count++] = "\n";
1771 fragstrings_list[fragstrings_count++] = "\n";
1776 R_CompileShader_AddStaticParms(mode, permutation);
1777 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1778 vertstrings_count += shaderstaticparms_count;
1779 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1780 geomstrings_count += shaderstaticparms_count;
1781 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1782 fragstrings_count += shaderstaticparms_count;
1784 // replace spaces in the cachename with _ characters
1785 for (i = 0;cachename[i];i++)
1786 if (cachename[i] == ' ')
1789 // now append the shader text itself
1790 vertstrings_list[vertstrings_count++] = sourcestring;
1791 geomstrings_list[geomstrings_count++] = sourcestring;
1792 fragstrings_list[fragstrings_count++] = sourcestring;
1794 vertstring_length = 0;
1795 for (i = 0;i < vertstrings_count;i++)
1796 vertstring_length += (int)strlen(vertstrings_list[i]);
1797 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1798 for (i = 0;i < vertstrings_count;t += (int)strlen(vertstrings_list[i]), i++)
1799 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1801 geomstring_length = 0;
1802 for (i = 0;i < geomstrings_count;i++)
1803 geomstring_length += (int)strlen(geomstrings_list[i]);
1804 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1805 for (i = 0;i < geomstrings_count;t += (int)strlen(geomstrings_list[i]), i++)
1806 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1808 fragstring_length = 0;
1809 for (i = 0;i < fragstrings_count;i++)
1810 fragstring_length += (int)strlen(fragstrings_list[i]);
1811 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1812 for (i = 0;i < fragstrings_count;t += (int)strlen(fragstrings_list[i]), i++)
1813 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1815 // try to load the cached shader, or generate one
1816 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1818 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1819 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1821 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1825 Mem_Free(vertstring);
1827 Mem_Free(geomstring);
1829 Mem_Free(fragstring);
1831 Mem_Free(sourcestring);
1834 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1835 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1836 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);}
1837 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);}
1838 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);}
1839 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);}
1841 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1842 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1843 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);}
1844 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);}
1845 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);}
1846 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);}
1848 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1850 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1851 if (r_hlsl_permutation != perm)
1853 r_hlsl_permutation = perm;
1854 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1856 if (!r_hlsl_permutation->compiled)
1857 R_HLSL_CompilePermutation(perm, mode, permutation);
1858 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1860 // remove features until we find a valid permutation
1862 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1864 // reduce i more quickly whenever it would not remove any bits
1865 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1866 if (!(permutation & j))
1869 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1870 if (!r_hlsl_permutation->compiled)
1871 R_HLSL_CompilePermutation(perm, mode, permutation);
1872 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1875 if (i >= SHADERPERMUTATION_COUNT)
1877 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1878 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1879 return; // no bit left to clear, entire mode is broken
1883 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1884 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1886 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1887 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1888 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1892 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1894 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1895 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1896 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1897 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1900 void R_GLSL_Restart_f(void)
1902 unsigned int i, limit;
1903 if (glslshaderstring)
1904 Mem_Free(glslshaderstring);
1905 glslshaderstring = NULL;
1906 if (hlslshaderstring)
1907 Mem_Free(hlslshaderstring);
1908 hlslshaderstring = NULL;
1909 switch(vid.renderpath)
1911 case RENDERPATH_D3D9:
1914 r_hlsl_permutation_t *p;
1915 r_hlsl_permutation = NULL;
1916 limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1917 for (i = 0;i < limit;i++)
1919 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1921 if (p->vertexshader)
1922 IDirect3DVertexShader9_Release(p->vertexshader);
1924 IDirect3DPixelShader9_Release(p->pixelshader);
1925 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1928 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1932 case RENDERPATH_D3D10:
1933 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1935 case RENDERPATH_D3D11:
1936 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1938 case RENDERPATH_GL20:
1939 case RENDERPATH_GLES2:
1941 r_glsl_permutation_t *p;
1942 r_glsl_permutation = NULL;
1943 limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1944 for (i = 0;i < limit;i++)
1946 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1948 GL_Backend_FreeProgram(p->program);
1949 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1952 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1955 case RENDERPATH_GL11:
1956 case RENDERPATH_GL13:
1957 case RENDERPATH_GLES1:
1959 case RENDERPATH_SOFT:
1964 static void R_GLSL_DumpShader_f(void)
1966 int i, language, mode, dupe;
1968 shadermodeinfo_t *modeinfo;
1971 for (language = 0;language < 2;language++)
1973 modeinfo = (language == 0 ? glslshadermodeinfo : hlslshadermodeinfo);
1974 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1976 // don't dump the same file multiple times (most or all shaders come from the same file)
1977 for (dupe = mode - 1;dupe >= 0;dupe--)
1978 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1982 text = R_GetShaderText(modeinfo[mode].filename, false, true);
1985 file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
1988 FS_Print(file, "/* The engine may define the following macros:\n");
1989 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1990 for (i = 0;i < SHADERMODE_COUNT;i++)
1991 FS_Print(file, modeinfo[i].pretext);
1992 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1993 FS_Print(file, shaderpermutationinfo[i].pretext);
1994 FS_Print(file, "*/\n");
1995 FS_Print(file, text);
1997 Con_Printf("%s written\n", modeinfo[mode].filename);
2000 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
2006 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
2008 unsigned int permutation = 0;
2009 if (r_trippy.integer && !notrippy)
2010 permutation |= SHADERPERMUTATION_TRIPPY;
2011 permutation |= SHADERPERMUTATION_VIEWTINT;
2013 permutation |= SHADERPERMUTATION_DIFFUSE;
2015 permutation |= SHADERPERMUTATION_SPECULAR;
2016 if (texturemode == GL_MODULATE)
2017 permutation |= SHADERPERMUTATION_COLORMAPPING;
2018 else if (texturemode == GL_ADD)
2019 permutation |= SHADERPERMUTATION_GLOW;
2020 else if (texturemode == GL_DECAL)
2021 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2022 if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
2023 permutation |= SHADERPERMUTATION_GAMMARAMPS;
2024 if (suppresstexalpha)
2025 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2027 texturemode = GL_MODULATE;
2028 if (vid.allowalphatocoverage)
2029 GL_AlphaToCoverage(false);
2030 switch (vid.renderpath)
2032 case RENDERPATH_D3D9:
2034 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
2035 R_Mesh_TexBind(GL20TU_FIRST , first );
2036 R_Mesh_TexBind(GL20TU_SECOND, second);
2037 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
2038 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2041 case RENDERPATH_D3D10:
2042 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2044 case RENDERPATH_D3D11:
2045 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2047 case RENDERPATH_GL20:
2048 case RENDERPATH_GLES2:
2049 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2050 if (r_glsl_permutation->tex_Texture_First >= 0)
2051 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2052 if (r_glsl_permutation->tex_Texture_Second >= 0)
2053 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2054 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2055 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2057 case RENDERPATH_GL13:
2058 case RENDERPATH_GLES1:
2059 R_Mesh_TexBind(0, first );
2060 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2061 R_Mesh_TexMatrix(0, NULL);
2062 R_Mesh_TexBind(1, second);
2065 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2066 R_Mesh_TexMatrix(1, NULL);
2069 case RENDERPATH_GL11:
2070 R_Mesh_TexBind(0, first );
2071 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2072 R_Mesh_TexMatrix(0, NULL);
2074 case RENDERPATH_SOFT:
2075 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2076 R_Mesh_TexBind(GL20TU_FIRST , first );
2077 R_Mesh_TexBind(GL20TU_SECOND, second);
2082 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2084 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2087 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2089 unsigned int permutation = 0;
2090 if (r_trippy.integer && !notrippy)
2091 permutation |= SHADERPERMUTATION_TRIPPY;
2093 permutation |= SHADERPERMUTATION_DEPTHRGB;
2095 permutation |= SHADERPERMUTATION_SKELETAL;
2097 if (vid.allowalphatocoverage)
2098 GL_AlphaToCoverage(false);
2099 switch (vid.renderpath)
2101 case RENDERPATH_D3D9:
2103 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2106 case RENDERPATH_D3D10:
2107 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2109 case RENDERPATH_D3D11:
2110 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2112 case RENDERPATH_GL20:
2113 case RENDERPATH_GLES2:
2114 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2115 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2116 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);
2119 case RENDERPATH_GL13:
2120 case RENDERPATH_GLES1:
2121 R_Mesh_TexBind(0, 0);
2122 R_Mesh_TexBind(1, 0);
2124 case RENDERPATH_GL11:
2125 R_Mesh_TexBind(0, 0);
2127 case RENDERPATH_SOFT:
2128 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2133 extern qboolean r_shadow_usingdeferredprepass;
2134 extern rtexture_t *r_shadow_attenuationgradienttexture;
2135 extern rtexture_t *r_shadow_attenuation2dtexture;
2136 extern rtexture_t *r_shadow_attenuation3dtexture;
2137 extern qboolean r_shadow_usingshadowmap2d;
2138 extern qboolean r_shadow_usingshadowmaportho;
2139 extern float r_shadow_shadowmap_texturescale[2];
2140 extern float r_shadow_shadowmap_parameters[4];
2141 extern qboolean r_shadow_shadowmapvsdct;
2142 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2143 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2144 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2145 extern matrix4x4_t r_shadow_shadowmapmatrix;
2146 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2147 extern int r_shadow_prepass_width;
2148 extern int r_shadow_prepass_height;
2149 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2150 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2151 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2152 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2154 #define BLENDFUNC_ALLOWS_COLORMOD 1
2155 #define BLENDFUNC_ALLOWS_FOG 2
2156 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2157 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2158 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2159 static int R_BlendFuncFlags(int src, int dst)
2163 // a blendfunc allows colormod if:
2164 // a) it can never keep the destination pixel invariant, or
2165 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2166 // this is to prevent unintended side effects from colormod
2168 // a blendfunc allows fog if:
2169 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2170 // this is to prevent unintended side effects from fog
2172 // these checks are the output of fogeval.pl
2174 r |= BLENDFUNC_ALLOWS_COLORMOD;
2175 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2176 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2177 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2178 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2179 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2180 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2181 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2182 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2183 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2184 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2185 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2186 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2187 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2188 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2189 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2190 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2191 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2192 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2193 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2194 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2195 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2200 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)
2202 // select a permutation of the lighting shader appropriate to this
2203 // combination of texture, entity, light source, and fogging, only use the
2204 // minimum features necessary to avoid wasting rendering time in the
2205 // fragment shader on features that are not being used
2206 unsigned int permutation = 0;
2207 unsigned int mode = 0;
2209 static float dummy_colormod[3] = {1, 1, 1};
2210 float *colormod = rsurface.colormod;
2212 matrix4x4_t tempmatrix;
2213 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2214 if (r_trippy.integer && !notrippy)
2215 permutation |= SHADERPERMUTATION_TRIPPY;
2216 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2217 permutation |= SHADERPERMUTATION_ALPHAKILL;
2218 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_OCCLUDE)
2219 permutation |= SHADERPERMUTATION_OCCLUDE;
2220 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2221 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2222 if (rsurfacepass == RSURFPASS_BACKGROUND)
2224 // distorted background
2225 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2227 mode = SHADERMODE_WATER;
2228 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2229 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2230 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2232 // this is the right thing to do for wateralpha
2233 GL_BlendFunc(GL_ONE, GL_ZERO);
2234 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2238 // this is the right thing to do for entity alpha
2239 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2240 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2243 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2245 mode = SHADERMODE_REFRACTION;
2246 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2247 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2248 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2249 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2253 mode = SHADERMODE_GENERIC;
2254 permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2255 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2256 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2258 if (vid.allowalphatocoverage)
2259 GL_AlphaToCoverage(false);
2261 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2263 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2265 switch(rsurface.texture->offsetmapping)
2267 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2268 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2269 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2270 case OFFSETMAPPING_OFF: break;
2273 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2274 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2275 // normalmap (deferred prepass), may use alpha test on diffuse
2276 mode = SHADERMODE_DEFERREDGEOMETRY;
2277 GL_BlendFunc(GL_ONE, GL_ZERO);
2278 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2279 if (vid.allowalphatocoverage)
2280 GL_AlphaToCoverage(false);
2282 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2284 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2286 switch(rsurface.texture->offsetmapping)
2288 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2289 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2290 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2291 case OFFSETMAPPING_OFF: break;
2294 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2295 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2296 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2297 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2299 mode = SHADERMODE_LIGHTSOURCE;
2300 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2301 permutation |= SHADERPERMUTATION_CUBEFILTER;
2302 if (diffusescale > 0)
2303 permutation |= SHADERPERMUTATION_DIFFUSE;
2304 if (specularscale > 0)
2305 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2306 if (r_refdef.fogenabled)
2307 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2308 if (rsurface.texture->colormapping)
2309 permutation |= SHADERPERMUTATION_COLORMAPPING;
2310 if (r_shadow_usingshadowmap2d)
2312 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2313 if(r_shadow_shadowmapvsdct)
2314 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2316 if (r_shadow_shadowmap2ddepthbuffer)
2317 permutation |= SHADERPERMUTATION_DEPTHRGB;
2319 if (rsurface.texture->reflectmasktexture)
2320 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2321 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2322 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2323 if (vid.allowalphatocoverage)
2324 GL_AlphaToCoverage(false);
2326 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2328 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2330 switch(rsurface.texture->offsetmapping)
2332 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2333 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2334 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2335 case OFFSETMAPPING_OFF: break;
2338 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2339 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2340 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2341 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2342 // unshaded geometry (fullbright or ambient model lighting)
2343 mode = SHADERMODE_FLATCOLOR;
2344 ambientscale = diffusescale = specularscale = 0;
2345 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2346 permutation |= SHADERPERMUTATION_GLOW;
2347 if (r_refdef.fogenabled)
2348 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2349 if (rsurface.texture->colormapping)
2350 permutation |= SHADERPERMUTATION_COLORMAPPING;
2351 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2353 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2354 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2356 if (r_shadow_shadowmap2ddepthbuffer)
2357 permutation |= SHADERPERMUTATION_DEPTHRGB;
2359 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2360 permutation |= SHADERPERMUTATION_REFLECTION;
2361 if (rsurface.texture->reflectmasktexture)
2362 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2363 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2364 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2365 // when using alphatocoverage, we don't need alphakill
2366 if (vid.allowalphatocoverage)
2368 if (r_transparent_alphatocoverage.integer)
2370 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2371 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2374 GL_AlphaToCoverage(false);
2377 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2379 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2381 switch(rsurface.texture->offsetmapping)
2383 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2384 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2385 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2386 case OFFSETMAPPING_OFF: break;
2389 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2390 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2391 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2392 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2393 // directional model lighting
2394 mode = SHADERMODE_LIGHTDIRECTION;
2395 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2396 permutation |= SHADERPERMUTATION_GLOW;
2397 permutation |= SHADERPERMUTATION_DIFFUSE;
2398 if (specularscale > 0)
2399 permutation |= SHADERPERMUTATION_SPECULAR;
2400 if (r_refdef.fogenabled)
2401 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2402 if (rsurface.texture->colormapping)
2403 permutation |= SHADERPERMUTATION_COLORMAPPING;
2404 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2406 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2407 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2409 if (r_shadow_shadowmap2ddepthbuffer)
2410 permutation |= SHADERPERMUTATION_DEPTHRGB;
2412 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2413 permutation |= SHADERPERMUTATION_REFLECTION;
2414 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2415 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2416 if (rsurface.texture->reflectmasktexture)
2417 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2418 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2420 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2421 if (r_shadow_bouncegriddirectional)
2422 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2424 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2425 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2426 // when using alphatocoverage, we don't need alphakill
2427 if (vid.allowalphatocoverage)
2429 if (r_transparent_alphatocoverage.integer)
2431 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2432 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2435 GL_AlphaToCoverage(false);
2438 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2440 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2442 switch(rsurface.texture->offsetmapping)
2444 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2445 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2446 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2447 case OFFSETMAPPING_OFF: break;
2450 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2451 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2452 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2453 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2454 // ambient model lighting
2455 mode = SHADERMODE_LIGHTDIRECTION;
2456 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2457 permutation |= SHADERPERMUTATION_GLOW;
2458 if (r_refdef.fogenabled)
2459 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2460 if (rsurface.texture->colormapping)
2461 permutation |= SHADERPERMUTATION_COLORMAPPING;
2462 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2464 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2465 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2467 if (r_shadow_shadowmap2ddepthbuffer)
2468 permutation |= SHADERPERMUTATION_DEPTHRGB;
2470 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2471 permutation |= SHADERPERMUTATION_REFLECTION;
2472 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2473 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2474 if (rsurface.texture->reflectmasktexture)
2475 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2476 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2478 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2479 if (r_shadow_bouncegriddirectional)
2480 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2482 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2483 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2484 // when using alphatocoverage, we don't need alphakill
2485 if (vid.allowalphatocoverage)
2487 if (r_transparent_alphatocoverage.integer)
2489 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2490 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2493 GL_AlphaToCoverage(false);
2498 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2500 switch(rsurface.texture->offsetmapping)
2502 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2503 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2504 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2505 case OFFSETMAPPING_OFF: break;
2508 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2509 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2510 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2511 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2513 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2514 permutation |= SHADERPERMUTATION_GLOW;
2515 if (r_refdef.fogenabled)
2516 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2517 if (rsurface.texture->colormapping)
2518 permutation |= SHADERPERMUTATION_COLORMAPPING;
2519 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2521 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2522 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2524 if (r_shadow_shadowmap2ddepthbuffer)
2525 permutation |= SHADERPERMUTATION_DEPTHRGB;
2527 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2528 permutation |= SHADERPERMUTATION_REFLECTION;
2529 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2530 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2531 if (rsurface.texture->reflectmasktexture)
2532 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2533 if (FAKELIGHT_ENABLED)
2535 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2536 mode = SHADERMODE_FAKELIGHT;
2537 permutation |= SHADERPERMUTATION_DIFFUSE;
2538 if (specularscale > 0)
2539 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2541 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2543 // deluxemapping (light direction texture)
2544 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2545 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2547 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2548 permutation |= SHADERPERMUTATION_DIFFUSE;
2549 if (specularscale > 0)
2550 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2552 else if (r_glsl_deluxemapping.integer >= 2)
2554 // fake deluxemapping (uniform light direction in tangentspace)
2555 if (rsurface.uselightmaptexture)
2556 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2558 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2559 permutation |= SHADERPERMUTATION_DIFFUSE;
2560 if (specularscale > 0)
2561 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2563 else if (rsurface.uselightmaptexture)
2565 // ordinary lightmapping (q1bsp, q3bsp)
2566 mode = SHADERMODE_LIGHTMAP;
2570 // ordinary vertex coloring (q3bsp)
2571 mode = SHADERMODE_VERTEXCOLOR;
2573 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2575 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2576 if (r_shadow_bouncegriddirectional)
2577 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2579 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2580 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2581 // when using alphatocoverage, we don't need alphakill
2582 if (vid.allowalphatocoverage)
2584 if (r_transparent_alphatocoverage.integer)
2586 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2587 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2590 GL_AlphaToCoverage(false);
2593 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2594 colormod = dummy_colormod;
2595 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2596 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2597 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2598 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2599 switch(vid.renderpath)
2601 case RENDERPATH_D3D9:
2603 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);
2604 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2605 R_SetupShader_SetPermutationHLSL(mode, permutation);
2606 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2607 if (mode == SHADERMODE_LIGHTSOURCE)
2609 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2610 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2614 if (mode == SHADERMODE_LIGHTDIRECTION)
2616 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2619 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2620 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2621 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2622 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2623 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2625 if (mode == SHADERMODE_LIGHTSOURCE)
2627 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2628 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2629 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2630 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2631 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2633 // additive passes are only darkened by fog, not tinted
2634 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2635 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2639 if (mode == SHADERMODE_FLATCOLOR)
2641 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2643 else if (mode == SHADERMODE_LIGHTDIRECTION)
2645 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]);
2646 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2647 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);
2648 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2649 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2650 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2651 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2655 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2656 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2657 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);
2658 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2659 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2661 // additive passes are only darkened by fog, not tinted
2662 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2663 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2665 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2666 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);
2667 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2668 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2669 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2670 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2671 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2672 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2673 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2674 if (mode == SHADERMODE_WATER)
2675 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2677 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2678 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2679 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2680 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));
2681 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2682 if (rsurface.texture->pantstexture)
2683 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2685 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2686 if (rsurface.texture->shirttexture)
2687 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2689 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2690 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2691 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2692 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2693 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2694 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2695 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2696 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2697 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2698 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2700 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2701 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2702 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2703 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2705 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2706 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2707 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2708 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2709 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2710 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2711 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2712 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2713 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2714 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2715 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2716 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2717 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2718 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2719 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2720 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2721 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2722 if (rsurfacepass == RSURFPASS_BACKGROUND)
2724 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2725 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2726 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2730 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2732 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2733 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2734 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2735 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2737 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2738 if (rsurface.rtlight)
2740 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2741 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2746 case RENDERPATH_D3D10:
2747 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2749 case RENDERPATH_D3D11:
2750 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2752 case RENDERPATH_GL20:
2753 case RENDERPATH_GLES2:
2754 if (!vid.useinterleavedarrays)
2756 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);
2757 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2758 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2759 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2760 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2761 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2762 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2763 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2764 R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2765 R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2766 R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2770 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);
2771 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2773 // this has to be after RSurf_PrepareVerticesForBatch
2774 if (rsurface.batchskeletaltransform3x4buffer)
2775 permutation |= SHADERPERMUTATION_SKELETAL;
2776 R_SetupShader_SetPermutationGLSL(mode, permutation);
2777 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2778 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);
2780 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2781 if (mode == SHADERMODE_LIGHTSOURCE)
2783 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2784 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2785 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2786 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2787 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2788 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);
2790 // additive passes are only darkened by fog, not tinted
2791 if (r_glsl_permutation->loc_FogColor >= 0)
2792 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2793 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);
2797 if (mode == SHADERMODE_FLATCOLOR)
2799 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2801 else if (mode == SHADERMODE_LIGHTDIRECTION)
2803 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]);
2804 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]);
2805 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);
2806 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2807 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2808 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]);
2809 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]);
2813 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]);
2814 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]);
2815 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);
2816 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2817 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2819 // additive passes are only darkened by fog, not tinted
2820 if (r_glsl_permutation->loc_FogColor >= 0)
2822 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2823 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2825 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2827 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);
2828 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]);
2829 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]);
2830 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]);
2831 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]);
2832 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2833 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2834 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);
2835 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]);
2837 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2838 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2839 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2840 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]);
2841 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]);
2843 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2844 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));
2845 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2846 if (r_glsl_permutation->loc_Color_Pants >= 0)
2848 if (rsurface.texture->pantstexture)
2849 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2851 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2853 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2855 if (rsurface.texture->shirttexture)
2856 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2858 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2860 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]);
2861 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2862 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2863 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2864 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2865 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2866 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2867 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2868 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2870 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);
2871 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2872 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]);
2873 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2874 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);}
2875 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2877 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2878 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2879 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2880 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2881 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2882 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2883 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2884 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2885 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2886 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2887 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2888 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2889 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2890 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2891 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);
2892 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2893 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2894 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2895 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2896 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2897 if (rsurfacepass == RSURFPASS_BACKGROUND)
2899 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);
2900 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);
2901 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);
2905 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);
2907 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2908 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2909 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2910 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2912 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture );
2913 if (rsurface.rtlight)
2915 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2916 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2919 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2922 case RENDERPATH_GL11:
2923 case RENDERPATH_GL13:
2924 case RENDERPATH_GLES1:
2926 case RENDERPATH_SOFT:
2927 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);
2928 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2929 R_SetupShader_SetPermutationSoft(mode, permutation);
2930 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2931 if (mode == SHADERMODE_LIGHTSOURCE)
2933 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2934 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2935 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2936 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2937 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2938 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2940 // additive passes are only darkened by fog, not tinted
2941 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2942 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2946 if (mode == SHADERMODE_FLATCOLOR)
2948 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2950 else if (mode == SHADERMODE_LIGHTDIRECTION)
2952 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]);
2953 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2954 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);
2955 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2956 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2957 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]);
2958 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2962 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2963 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2964 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);
2965 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2966 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2968 // additive passes are only darkened by fog, not tinted
2969 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2970 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2972 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2973 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);
2974 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]);
2975 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]);
2976 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]);
2977 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]);
2978 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2979 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2980 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2981 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2983 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2984 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2985 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2986 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2987 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]);
2989 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2990 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));
2991 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2992 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2994 if (rsurface.texture->pantstexture)
2995 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2997 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2999 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
3001 if (rsurface.texture->shirttexture)
3002 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
3004 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
3006 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
3007 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
3008 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
3009 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
3010 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
3011 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
3012 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3013 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3014 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
3016 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
3017 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
3018 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3019 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3021 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
3022 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
3023 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
3024 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
3025 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
3026 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
3027 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
3028 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
3029 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
3030 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
3031 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
3032 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
3033 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
3034 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
3035 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
3036 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
3037 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3038 if (rsurfacepass == RSURFPASS_BACKGROUND)
3040 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
3041 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
3042 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3046 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3048 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3049 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
3050 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
3051 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
3053 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
3054 if (rsurface.rtlight)
3056 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3057 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3064 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3066 // select a permutation of the lighting shader appropriate to this
3067 // combination of texture, entity, light source, and fogging, only use the
3068 // minimum features necessary to avoid wasting rendering time in the
3069 // fragment shader on features that are not being used
3070 unsigned int permutation = 0;
3071 unsigned int mode = 0;
3072 const float *lightcolorbase = rtlight->currentcolor;
3073 float ambientscale = rtlight->ambientscale;
3074 float diffusescale = rtlight->diffusescale;
3075 float specularscale = rtlight->specularscale;
3076 // this is the location of the light in view space
3077 vec3_t viewlightorigin;
3078 // this transforms from view space (camera) to light space (cubemap)
3079 matrix4x4_t viewtolight;
3080 matrix4x4_t lighttoview;
3081 float viewtolight16f[16];
3083 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3084 if (rtlight->currentcubemap != r_texture_whitecube)
3085 permutation |= SHADERPERMUTATION_CUBEFILTER;
3086 if (diffusescale > 0)
3087 permutation |= SHADERPERMUTATION_DIFFUSE;
3088 if (specularscale > 0 && r_shadow_gloss.integer > 0)
3089 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3090 if (r_shadow_usingshadowmap2d)
3092 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3093 if (r_shadow_shadowmapvsdct)
3094 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3096 if (r_shadow_shadowmap2ddepthbuffer)
3097 permutation |= SHADERPERMUTATION_DEPTHRGB;
3099 if (vid.allowalphatocoverage)
3100 GL_AlphaToCoverage(false);
3101 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3102 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3103 Matrix4x4_Invert_Full(&viewtolight, &lighttoview);
3104 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3105 switch(vid.renderpath)
3107 case RENDERPATH_D3D9:
3109 R_SetupShader_SetPermutationHLSL(mode, permutation);
3110 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3111 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3112 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3113 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3114 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3115 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3116 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3117 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);
3118 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3119 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3121 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3122 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3123 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3124 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2ddepthtexture );
3125 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3128 case RENDERPATH_D3D10:
3129 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3131 case RENDERPATH_D3D11:
3132 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3134 case RENDERPATH_GL20:
3135 case RENDERPATH_GLES2:
3136 R_SetupShader_SetPermutationGLSL(mode, permutation);
3137 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3138 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
3139 if (r_glsl_permutation->loc_DeferredColor_Ambient >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3140 if (r_glsl_permutation->loc_DeferredColor_Diffuse >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3141 if (r_glsl_permutation->loc_DeferredColor_Specular >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3142 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]);
3143 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]);
3144 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);
3145 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]);
3146 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
3148 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
3149 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
3150 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
3151 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2ddepthtexture );
3152 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
3154 case RENDERPATH_GL11:
3155 case RENDERPATH_GL13:
3156 case RENDERPATH_GLES1:
3158 case RENDERPATH_SOFT:
3159 R_SetupShader_SetPermutationGLSL(mode, permutation);
3160 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3161 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
3162 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3163 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3164 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3165 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3166 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]);
3167 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);
3168 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3169 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3171 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3172 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3173 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3174 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2ddepthtexture );
3175 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3180 #define SKINFRAME_HASH 1024
3184 unsigned int loadsequence; // incremented each level change
3185 memexpandablearray_t array;
3186 skinframe_t *hash[SKINFRAME_HASH];
3189 r_skinframe_t r_skinframe;
3191 void R_SkinFrame_PrepareForPurge(void)
3193 r_skinframe.loadsequence++;
3194 // wrap it without hitting zero
3195 if (r_skinframe.loadsequence >= 200)
3196 r_skinframe.loadsequence = 1;
3199 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3203 // mark the skinframe as used for the purging code
3204 skinframe->loadsequence = r_skinframe.loadsequence;
3207 void R_SkinFrame_Purge(void)
3211 for (i = 0;i < SKINFRAME_HASH;i++)
3213 for (s = r_skinframe.hash[i];s;s = s->next)
3215 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3217 if (s->merged == s->base)
3219 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3220 R_PurgeTexture(s->stain );s->stain = NULL;
3221 R_PurgeTexture(s->merged);s->merged = NULL;
3222 R_PurgeTexture(s->base );s->base = NULL;
3223 R_PurgeTexture(s->pants );s->pants = NULL;
3224 R_PurgeTexture(s->shirt );s->shirt = NULL;
3225 R_PurgeTexture(s->nmap );s->nmap = NULL;
3226 R_PurgeTexture(s->gloss );s->gloss = NULL;
3227 R_PurgeTexture(s->glow );s->glow = NULL;
3228 R_PurgeTexture(s->fog );s->fog = NULL;
3229 R_PurgeTexture(s->reflect);s->reflect = NULL;
3230 s->loadsequence = 0;
3236 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3238 char basename[MAX_QPATH];
3240 Image_StripImageExtension(name, basename, sizeof(basename));
3242 if( last == NULL ) {
3244 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3245 item = r_skinframe.hash[hashindex];
3250 // linearly search through the hash bucket
3251 for( ; item ; item = item->next ) {
3252 if( !strcmp( item->basename, basename ) ) {
3259 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3263 char basename[MAX_QPATH];
3265 Image_StripImageExtension(name, basename, sizeof(basename));
3267 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3268 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3269 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3273 rtexture_t *dyntexture;
3274 // check whether its a dynamic texture
3275 dyntexture = CL_GetDynTexture( basename );
3276 if (!add && !dyntexture)
3278 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3279 memset(item, 0, sizeof(*item));
3280 strlcpy(item->basename, basename, sizeof(item->basename));
3281 item->base = dyntexture; // either NULL or dyntexture handle
3282 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3283 item->comparewidth = comparewidth;
3284 item->compareheight = compareheight;
3285 item->comparecrc = comparecrc;
3286 item->next = r_skinframe.hash[hashindex];
3287 r_skinframe.hash[hashindex] = item;
3289 else if (textureflags & TEXF_FORCE_RELOAD)
3291 rtexture_t *dyntexture;
3292 // check whether its a dynamic texture
3293 dyntexture = CL_GetDynTexture( basename );
3294 if (!add && !dyntexture)
3296 if (item->merged == item->base)
3297 item->merged = NULL;
3298 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3299 R_PurgeTexture(item->stain );item->stain = NULL;
3300 R_PurgeTexture(item->merged);item->merged = NULL;
3301 R_PurgeTexture(item->base );item->base = NULL;
3302 R_PurgeTexture(item->pants );item->pants = NULL;
3303 R_PurgeTexture(item->shirt );item->shirt = NULL;
3304 R_PurgeTexture(item->nmap );item->nmap = NULL;
3305 R_PurgeTexture(item->gloss );item->gloss = NULL;
3306 R_PurgeTexture(item->glow );item->glow = NULL;
3307 R_PurgeTexture(item->fog );item->fog = NULL;
3308 R_PurgeTexture(item->reflect);item->reflect = NULL;
3309 item->loadsequence = 0;
3311 else if( item->base == NULL )
3313 rtexture_t *dyntexture;
3314 // check whether its a dynamic texture
3315 // 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]
3316 dyntexture = CL_GetDynTexture( basename );
3317 item->base = dyntexture; // either NULL or dyntexture handle
3320 R_SkinFrame_MarkUsed(item);
3324 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3326 unsigned long long avgcolor[5], wsum; \
3334 for(pix = 0; pix < cnt; ++pix) \
3337 for(comp = 0; comp < 3; ++comp) \
3339 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3342 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3344 for(comp = 0; comp < 3; ++comp) \
3345 avgcolor[comp] += getpixel * w; \
3348 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3349 avgcolor[4] += getpixel; \
3351 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3353 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3354 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3355 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3356 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3359 extern cvar_t gl_picmip;
3360 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3363 unsigned char *pixels;
3364 unsigned char *bumppixels;
3365 unsigned char *basepixels = NULL;
3366 int basepixels_width = 0;
3367 int basepixels_height = 0;
3368 skinframe_t *skinframe;
3369 rtexture_t *ddsbase = NULL;
3370 qboolean ddshasalpha = false;
3371 float ddsavgcolor[4];
3372 char basename[MAX_QPATH];
3373 int miplevel = R_PicmipForFlags(textureflags);
3374 int savemiplevel = miplevel;
3378 if (cls.state == ca_dedicated)
3381 // return an existing skinframe if already loaded
3382 // if loading of the first image fails, don't make a new skinframe as it
3383 // would cause all future lookups of this to be missing
3384 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3385 if (skinframe && skinframe->base)
3388 Image_StripImageExtension(name, basename, sizeof(basename));
3390 // check for DDS texture file first
3391 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3393 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3394 if (basepixels == NULL)
3398 // FIXME handle miplevel
3400 if (developer_loading.integer)
3401 Con_Printf("loading skin \"%s\"\n", name);
3403 // we've got some pixels to store, so really allocate this new texture now
3405 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3406 textureflags &= ~TEXF_FORCE_RELOAD;
3407 skinframe->stain = NULL;
3408 skinframe->merged = NULL;
3409 skinframe->base = NULL;
3410 skinframe->pants = NULL;
3411 skinframe->shirt = NULL;
3412 skinframe->nmap = NULL;
3413 skinframe->gloss = NULL;
3414 skinframe->glow = NULL;
3415 skinframe->fog = NULL;
3416 skinframe->reflect = NULL;
3417 skinframe->hasalpha = false;
3418 // we could store the q2animname here too
3422 skinframe->base = ddsbase;
3423 skinframe->hasalpha = ddshasalpha;
3424 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3425 if (r_loadfog && skinframe->hasalpha)
3426 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);
3427 //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]);
3431 basepixels_width = image_width;
3432 basepixels_height = image_height;
3433 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);
3434 if (textureflags & TEXF_ALPHA)
3436 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3438 if (basepixels[j] < 255)
3440 skinframe->hasalpha = true;
3444 if (r_loadfog && skinframe->hasalpha)
3446 // has transparent pixels
3447 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3448 for (j = 0;j < image_width * image_height * 4;j += 4)
3453 pixels[j+3] = basepixels[j+3];
3455 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);
3459 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3461 //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]);
3462 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3463 R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3464 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3465 R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3471 mymiplevel = savemiplevel;
3472 if (r_loadnormalmap)
3473 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);
3474 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3476 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3477 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3478 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3479 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3482 // _norm is the name used by tenebrae and has been adopted as standard
3483 if (r_loadnormalmap && skinframe->nmap == NULL)
3485 mymiplevel = savemiplevel;
3486 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3488 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);
3492 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3494 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3495 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3496 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);
3498 Mem_Free(bumppixels);
3500 else if (r_shadow_bumpscale_basetexture.value > 0)
3502 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3503 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3504 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);
3508 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3509 R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3513 // _luma is supported only for tenebrae compatibility
3514 // _glow is the preferred name
3515 mymiplevel = savemiplevel;
3516 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))))
3518 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);
3520 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3521 R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3523 Mem_Free(pixels);pixels = NULL;
3526 mymiplevel = savemiplevel;
3527 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3529 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);
3531 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3532 R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3538 mymiplevel = savemiplevel;
3539 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3541 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);
3543 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3544 R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3550 mymiplevel = savemiplevel;
3551 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3553 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);
3555 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3556 R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3562 mymiplevel = savemiplevel;
3563 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3565 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);
3567 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3568 R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3575 Mem_Free(basepixels);
3580 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3581 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3584 unsigned char *temp1, *temp2;
3585 skinframe_t *skinframe;
3588 if (cls.state == ca_dedicated)
3591 // if already loaded just return it, otherwise make a new skinframe
3592 skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3593 if (skinframe->base)
3595 textureflags &= ~TEXF_FORCE_RELOAD;
3597 skinframe->stain = NULL;
3598 skinframe->merged = NULL;
3599 skinframe->base = NULL;
3600 skinframe->pants = NULL;
3601 skinframe->shirt = NULL;
3602 skinframe->nmap = NULL;
3603 skinframe->gloss = NULL;
3604 skinframe->glow = NULL;
3605 skinframe->fog = NULL;
3606 skinframe->reflect = NULL;
3607 skinframe->hasalpha = false;
3609 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3613 if (developer_loading.integer)
3614 Con_Printf("loading 32bit skin \"%s\"\n", name);
3616 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3618 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3619 temp2 = temp1 + width * height * 4;
3620 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3621 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);
3624 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3625 if (textureflags & TEXF_ALPHA)
3627 for (i = 3;i < width * height * 4;i += 4)
3629 if (skindata[i] < 255)
3631 skinframe->hasalpha = true;
3635 if (r_loadfog && skinframe->hasalpha)
3637 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3638 memcpy(fogpixels, skindata, width * height * 4);
3639 for (i = 0;i < width * height * 4;i += 4)
3640 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3641 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3642 Mem_Free(fogpixels);
3646 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3647 //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]);
3652 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3656 skinframe_t *skinframe;
3658 if (cls.state == ca_dedicated)
3661 // if already loaded just return it, otherwise make a new skinframe
3662 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3663 if (skinframe->base)
3665 //textureflags &= ~TEXF_FORCE_RELOAD;
3667 skinframe->stain = NULL;
3668 skinframe->merged = NULL;
3669 skinframe->base = NULL;
3670 skinframe->pants = NULL;
3671 skinframe->shirt = NULL;
3672 skinframe->nmap = NULL;
3673 skinframe->gloss = NULL;
3674 skinframe->glow = NULL;
3675 skinframe->fog = NULL;
3676 skinframe->reflect = NULL;
3677 skinframe->hasalpha = false;
3679 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3683 if (developer_loading.integer)
3684 Con_Printf("loading quake skin \"%s\"\n", name);
3686 // 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)
3687 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3688 memcpy(skinframe->qpixels, skindata, width*height);
3689 skinframe->qwidth = width;
3690 skinframe->qheight = height;
3693 for (i = 0;i < width * height;i++)
3694 featuresmask |= palette_featureflags[skindata[i]];
3696 skinframe->hasalpha = false;
3699 skinframe->hasalpha = true;
3700 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3701 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3702 skinframe->qgeneratemerged = true;
3703 skinframe->qgeneratebase = skinframe->qhascolormapping;
3704 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3706 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3707 //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]);
3712 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3716 unsigned char *skindata;
3719 if (!skinframe->qpixels)
3722 if (!skinframe->qhascolormapping)
3723 colormapped = false;
3727 if (!skinframe->qgeneratebase)
3732 if (!skinframe->qgeneratemerged)
3736 width = skinframe->qwidth;
3737 height = skinframe->qheight;
3738 skindata = skinframe->qpixels;
3740 if (skinframe->qgeneratenmap)
3742 unsigned char *temp1, *temp2;
3743 skinframe->qgeneratenmap = false;
3744 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3745 temp2 = temp1 + width * height * 4;
3746 // use either a custom palette or the quake palette
3747 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3748 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3749 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);
3753 if (skinframe->qgenerateglow)
3755 skinframe->qgenerateglow = false;
3756 if (skinframe->hasalpha) // fence textures
3757 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 | TEXF_ALPHA, -1, palette_bgra_onlyfullbrights_transparent); // glow
3759 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
3764 skinframe->qgeneratebase = false;
3765 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);
3766 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);
3767 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);
3771 skinframe->qgeneratemerged = false;
3772 if (skinframe->hasalpha) // fence textures
3773 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags | TEXF_ALPHA, -1, skinframe->glow ? palette_bgra_nofullbrights_transparent : palette_bgra_transparent);
3775 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);
3778 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3780 Mem_Free(skinframe->qpixels);
3781 skinframe->qpixels = NULL;
3785 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)
3788 skinframe_t *skinframe;
3791 if (cls.state == ca_dedicated)
3794 // if already loaded just return it, otherwise make a new skinframe
3795 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3796 if (skinframe->base)
3798 textureflags &= ~TEXF_FORCE_RELOAD;
3800 skinframe->stain = NULL;
3801 skinframe->merged = NULL;
3802 skinframe->base = NULL;
3803 skinframe->pants = NULL;
3804 skinframe->shirt = NULL;
3805 skinframe->nmap = NULL;
3806 skinframe->gloss = NULL;
3807 skinframe->glow = NULL;
3808 skinframe->fog = NULL;
3809 skinframe->reflect = NULL;
3810 skinframe->hasalpha = false;
3812 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3816 if (developer_loading.integer)
3817 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3819 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3820 if (textureflags & TEXF_ALPHA)
3822 for (i = 0;i < width * height;i++)
3824 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3826 skinframe->hasalpha = true;
3830 if (r_loadfog && skinframe->hasalpha)
3831 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3834 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3835 //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]);
3840 skinframe_t *R_SkinFrame_LoadMissing(void)
3842 skinframe_t *skinframe;
3844 if (cls.state == ca_dedicated)
3847 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3848 skinframe->stain = NULL;
3849 skinframe->merged = NULL;
3850 skinframe->base = NULL;
3851 skinframe->pants = NULL;
3852 skinframe->shirt = NULL;
3853 skinframe->nmap = NULL;
3854 skinframe->gloss = NULL;
3855 skinframe->glow = NULL;
3856 skinframe->fog = NULL;
3857 skinframe->reflect = NULL;
3858 skinframe->hasalpha = false;
3860 skinframe->avgcolor[0] = rand() / RAND_MAX;
3861 skinframe->avgcolor[1] = rand() / RAND_MAX;
3862 skinframe->avgcolor[2] = rand() / RAND_MAX;
3863 skinframe->avgcolor[3] = 1;
3868 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3869 typedef struct suffixinfo_s
3872 qboolean flipx, flipy, flipdiagonal;
3875 static suffixinfo_t suffix[3][6] =
3878 {"px", false, false, false},
3879 {"nx", false, false, false},
3880 {"py", false, false, false},
3881 {"ny", false, false, false},
3882 {"pz", false, false, false},
3883 {"nz", false, false, false}
3886 {"posx", false, false, false},
3887 {"negx", false, false, false},
3888 {"posy", false, false, false},
3889 {"negy", false, false, false},
3890 {"posz", false, false, false},
3891 {"negz", false, false, false}
3894 {"rt", true, false, true},
3895 {"lf", false, true, true},
3896 {"ft", true, true, false},
3897 {"bk", false, false, false},
3898 {"up", true, false, true},
3899 {"dn", true, false, true}
3903 static int componentorder[4] = {0, 1, 2, 3};
3905 static rtexture_t *R_LoadCubemap(const char *basename)
3907 int i, j, cubemapsize;
3908 unsigned char *cubemappixels, *image_buffer;
3909 rtexture_t *cubemaptexture;
3911 // must start 0 so the first loadimagepixels has no requested width/height
3913 cubemappixels = NULL;
3914 cubemaptexture = NULL;
3915 // keep trying different suffix groups (posx, px, rt) until one loads
3916 for (j = 0;j < 3 && !cubemappixels;j++)
3918 // load the 6 images in the suffix group
3919 for (i = 0;i < 6;i++)
3921 // generate an image name based on the base and and suffix
3922 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3924 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3926 // an image loaded, make sure width and height are equal
3927 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3929 // if this is the first image to load successfully, allocate the cubemap memory
3930 if (!cubemappixels && image_width >= 1)
3932 cubemapsize = image_width;
3933 // note this clears to black, so unavailable sides are black
3934 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3936 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3938 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);
3941 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3943 Mem_Free(image_buffer);
3947 // if a cubemap loaded, upload it
3950 if (developer_loading.integer)
3951 Con_Printf("loading cubemap \"%s\"\n", basename);
3953 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);
3954 Mem_Free(cubemappixels);
3958 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3959 if (developer_loading.integer)
3961 Con_Printf("(tried tried images ");
3962 for (j = 0;j < 3;j++)
3963 for (i = 0;i < 6;i++)
3964 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3965 Con_Print(" and was unable to find any of them).\n");
3968 return cubemaptexture;
3971 rtexture_t *R_GetCubemap(const char *basename)
3974 for (i = 0;i < r_texture_numcubemaps;i++)
3975 if (r_texture_cubemaps[i] != NULL)
3976 if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3977 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3978 if (i >= MAX_CUBEMAPS || !r_main_mempool)
3979 return r_texture_whitecube;
3980 r_texture_numcubemaps++;
3981 r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3982 strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3983 r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3984 return r_texture_cubemaps[i]->texture;
3987 static void R_Main_FreeViewCache(void)
3989 if (r_refdef.viewcache.entityvisible)
3990 Mem_Free(r_refdef.viewcache.entityvisible);
3991 if (r_refdef.viewcache.world_pvsbits)
3992 Mem_Free(r_refdef.viewcache.world_pvsbits);
3993 if (r_refdef.viewcache.world_leafvisible)
3994 Mem_Free(r_refdef.viewcache.world_leafvisible);
3995 if (r_refdef.viewcache.world_surfacevisible)
3996 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3997 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
4000 static void R_Main_ResizeViewCache(void)
4002 int numentities = r_refdef.scene.numentities;
4003 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
4004 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
4005 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
4006 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
4007 if (r_refdef.viewcache.maxentities < numentities)
4009 r_refdef.viewcache.maxentities = numentities;
4010 if (r_refdef.viewcache.entityvisible)
4011 Mem_Free(r_refdef.viewcache.entityvisible);
4012 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
4014 if (r_refdef.viewcache.world_numclusters != numclusters)
4016 r_refdef.viewcache.world_numclusters = numclusters;
4017 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
4018 if (r_refdef.viewcache.world_pvsbits)
4019 Mem_Free(r_refdef.viewcache.world_pvsbits);
4020 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
4022 if (r_refdef.viewcache.world_numleafs != numleafs)
4024 r_refdef.viewcache.world_numleafs = numleafs;
4025 if (r_refdef.viewcache.world_leafvisible)
4026 Mem_Free(r_refdef.viewcache.world_leafvisible);
4027 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
4029 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
4031 r_refdef.viewcache.world_numsurfaces = numsurfaces;
4032 if (r_refdef.viewcache.world_surfacevisible)
4033 Mem_Free(r_refdef.viewcache.world_surfacevisible);
4034 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
4038 extern rtexture_t *loadingscreentexture;
4039 static void gl_main_start(void)
4041 loadingscreentexture = NULL;
4042 r_texture_blanknormalmap = NULL;
4043 r_texture_white = NULL;
4044 r_texture_grey128 = NULL;
4045 r_texture_black = NULL;
4046 r_texture_whitecube = NULL;
4047 r_texture_normalizationcube = NULL;
4048 r_texture_fogattenuation = NULL;
4049 r_texture_fogheighttexture = NULL;
4050 r_texture_gammaramps = NULL;
4051 r_texture_numcubemaps = 0;
4052 r_uniformbufferalignment = 32;
4054 r_loaddds = r_texture_dds_load.integer != 0;
4055 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
4057 switch(vid.renderpath)
4059 case RENDERPATH_GL20:
4060 case RENDERPATH_D3D9:
4061 case RENDERPATH_D3D10:
4062 case RENDERPATH_D3D11:
4063 case RENDERPATH_SOFT:
4064 case RENDERPATH_GLES2:
4065 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4066 Cvar_SetValueQuick(&gl_combine, 1);
4067 Cvar_SetValueQuick(&r_glsl, 1);
4068 r_loadnormalmap = true;
4071 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
4072 if (vid.support.arb_uniform_buffer_object)
4073 qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4076 case RENDERPATH_GL13:
4077 case RENDERPATH_GLES1:
4078 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4079 Cvar_SetValueQuick(&gl_combine, 1);
4080 Cvar_SetValueQuick(&r_glsl, 0);
4081 r_loadnormalmap = false;
4082 r_loadgloss = false;
4085 case RENDERPATH_GL11:
4086 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4087 Cvar_SetValueQuick(&gl_combine, 0);
4088 Cvar_SetValueQuick(&r_glsl, 0);
4089 r_loadnormalmap = false;
4090 r_loadgloss = false;
4096 R_FrameData_Reset();
4097 R_BufferData_Reset();
4101 memset(r_queries, 0, sizeof(r_queries));
4103 r_qwskincache = NULL;
4104 r_qwskincache_size = 0;
4106 // due to caching of texture_t references, the collision cache must be reset
4107 Collision_Cache_Reset(true);
4109 // set up r_skinframe loading system for textures
4110 memset(&r_skinframe, 0, sizeof(r_skinframe));
4111 r_skinframe.loadsequence = 1;
4112 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4114 r_main_texturepool = R_AllocTexturePool();
4115 R_BuildBlankTextures();
4117 if (vid.support.arb_texture_cube_map)
4120 R_BuildNormalizationCube();
4122 r_texture_fogattenuation = NULL;
4123 r_texture_fogheighttexture = NULL;
4124 r_texture_gammaramps = NULL;
4125 //r_texture_fogintensity = NULL;
4126 memset(&r_fb, 0, sizeof(r_fb));
4127 r_glsl_permutation = NULL;
4128 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4129 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4130 glslshaderstring = NULL;
4132 r_hlsl_permutation = NULL;
4133 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4134 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4136 hlslshaderstring = NULL;
4137 memset(&r_svbsp, 0, sizeof (r_svbsp));
4139 memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4140 r_texture_numcubemaps = 0;
4142 r_refdef.fogmasktable_density = 0;
4145 // For Steelstorm Android
4146 // FIXME CACHE the program and reload
4147 // FIXME see possible combinations for SS:BR android
4148 Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
4149 R_SetupShader_SetPermutationGLSL(0, 12);
4150 R_SetupShader_SetPermutationGLSL(0, 13);
4151 R_SetupShader_SetPermutationGLSL(0, 8388621);
4152 R_SetupShader_SetPermutationGLSL(3, 0);
4153 R_SetupShader_SetPermutationGLSL(3, 2048);
4154 R_SetupShader_SetPermutationGLSL(5, 0);
4155 R_SetupShader_SetPermutationGLSL(5, 2);
4156 R_SetupShader_SetPermutationGLSL(5, 2048);
4157 R_SetupShader_SetPermutationGLSL(5, 8388608);
4158 R_SetupShader_SetPermutationGLSL(11, 1);
4159 R_SetupShader_SetPermutationGLSL(11, 2049);
4160 R_SetupShader_SetPermutationGLSL(11, 8193);
4161 R_SetupShader_SetPermutationGLSL(11, 10241);
4162 Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
4166 static void gl_main_shutdown(void)
4169 R_FrameData_Reset();
4170 R_BufferData_Reset();
4172 R_Main_FreeViewCache();
4174 switch(vid.renderpath)
4176 case RENDERPATH_GL11:
4177 case RENDERPATH_GL13:
4178 case RENDERPATH_GL20:
4179 case RENDERPATH_GLES1:
4180 case RENDERPATH_GLES2:
4181 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
4183 qglDeleteQueriesARB(r_maxqueries, r_queries);
4186 case RENDERPATH_D3D9:
4187 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4189 case RENDERPATH_D3D10:
4190 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4192 case RENDERPATH_D3D11:
4193 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4195 case RENDERPATH_SOFT:
4201 memset(r_queries, 0, sizeof(r_queries));
4203 r_qwskincache = NULL;
4204 r_qwskincache_size = 0;
4206 // clear out the r_skinframe state
4207 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4208 memset(&r_skinframe, 0, sizeof(r_skinframe));
4211 Mem_Free(r_svbsp.nodes);
4212 memset(&r_svbsp, 0, sizeof (r_svbsp));
4213 R_FreeTexturePool(&r_main_texturepool);
4214 loadingscreentexture = NULL;
4215 r_texture_blanknormalmap = NULL;
4216 r_texture_white = NULL;
4217 r_texture_grey128 = NULL;
4218 r_texture_black = NULL;
4219 r_texture_whitecube = NULL;
4220 r_texture_normalizationcube = NULL;
4221 r_texture_fogattenuation = NULL;
4222 r_texture_fogheighttexture = NULL;
4223 r_texture_gammaramps = NULL;
4224 r_texture_numcubemaps = 0;
4225 //r_texture_fogintensity = NULL;
4226 memset(&r_fb, 0, sizeof(r_fb));
4229 r_glsl_permutation = NULL;
4230 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4231 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4232 glslshaderstring = NULL;
4234 r_hlsl_permutation = NULL;
4235 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4236 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4238 hlslshaderstring = NULL;
4241 static void gl_main_newmap(void)
4243 // FIXME: move this code to client
4244 char *entities, entname[MAX_QPATH];
4246 Mem_Free(r_qwskincache);
4247 r_qwskincache = NULL;
4248 r_qwskincache_size = 0;
4251 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4252 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4254 CL_ParseEntityLump(entities);
4258 if (cl.worldmodel->brush.entities)
4259 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4261 R_Main_FreeViewCache();
4263 R_FrameData_Reset();
4264 R_BufferData_Reset();
4267 void GL_Main_Init(void)
4270 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4272 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4273 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4274 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4275 if (gamemode == GAME_NEHAHRA)
4277 Cvar_RegisterVariable (&gl_fogenable);
4278 Cvar_RegisterVariable (&gl_fogdensity);
4279 Cvar_RegisterVariable (&gl_fogred);
4280 Cvar_RegisterVariable (&gl_foggreen);
4281 Cvar_RegisterVariable (&gl_fogblue);
4282 Cvar_RegisterVariable (&gl_fogstart);
4283 Cvar_RegisterVariable (&gl_fogend);
4284 Cvar_RegisterVariable (&gl_skyclip);
4286 Cvar_RegisterVariable(&r_motionblur);
4287 Cvar_RegisterVariable(&r_damageblur);
4288 Cvar_RegisterVariable(&r_motionblur_averaging);
4289 Cvar_RegisterVariable(&r_motionblur_randomize);
4290 Cvar_RegisterVariable(&r_motionblur_minblur);
4291 Cvar_RegisterVariable(&r_motionblur_maxblur);
4292 Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4293 Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4294 Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4295 Cvar_RegisterVariable(&r_motionblur_mousefactor);
4296 Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4297 Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4298 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4299 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4300 Cvar_RegisterVariable(&r_equalize_entities_by);
4301 Cvar_RegisterVariable(&r_equalize_entities_to);
4302 Cvar_RegisterVariable(&r_depthfirst);
4303 Cvar_RegisterVariable(&r_useinfinitefarclip);
4304 Cvar_RegisterVariable(&r_farclip_base);
4305 Cvar_RegisterVariable(&r_farclip_world);
4306 Cvar_RegisterVariable(&r_nearclip);
4307 Cvar_RegisterVariable(&r_deformvertexes);
4308 Cvar_RegisterVariable(&r_transparent);
4309 Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4310 Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4311 Cvar_RegisterVariable(&r_transparent_useplanardistance);
4312 Cvar_RegisterVariable(&r_showoverdraw);
4313 Cvar_RegisterVariable(&r_showbboxes);
4314 Cvar_RegisterVariable(&r_showsurfaces);
4315 Cvar_RegisterVariable(&r_showtris);
4316 Cvar_RegisterVariable(&r_shownormals);
4317 Cvar_RegisterVariable(&r_showlighting);
4318 Cvar_RegisterVariable(&r_showshadowvolumes);
4319 Cvar_RegisterVariable(&r_showcollisionbrushes);
4320 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4321 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4322 Cvar_RegisterVariable(&r_showdisabledepthtest);
4323 Cvar_RegisterVariable(&r_drawportals);
4324 Cvar_RegisterVariable(&r_drawentities);
4325 Cvar_RegisterVariable(&r_draw2d);
4326 Cvar_RegisterVariable(&r_drawworld);
4327 Cvar_RegisterVariable(&r_cullentities_trace);
4328 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4329 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4330 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4331 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4332 Cvar_RegisterVariable(&r_sortentities);
4333 Cvar_RegisterVariable(&r_drawviewmodel);
4334 Cvar_RegisterVariable(&r_drawexteriormodel);
4335 Cvar_RegisterVariable(&r_speeds);
4336 Cvar_RegisterVariable(&r_fullbrights);
4337 Cvar_RegisterVariable(&r_wateralpha);
4338 Cvar_RegisterVariable(&r_dynamic);
4339 Cvar_RegisterVariable(&r_fakelight);
4340 Cvar_RegisterVariable(&r_fakelight_intensity);
4341 Cvar_RegisterVariable(&r_fullbright);
4342 Cvar_RegisterVariable(&r_shadows);
4343 Cvar_RegisterVariable(&r_shadows_darken);
4344 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4345 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4346 Cvar_RegisterVariable(&r_shadows_throwdistance);
4347 Cvar_RegisterVariable(&r_shadows_throwdirection);
4348 Cvar_RegisterVariable(&r_shadows_focus);
4349 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4350 Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4351 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4352 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4353 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4354 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4355 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4356 Cvar_RegisterVariable(&r_fog_exp2);
4357 Cvar_RegisterVariable(&r_fog_clear);
4358 Cvar_RegisterVariable(&r_drawfog);
4359 Cvar_RegisterVariable(&r_transparentdepthmasking);
4360 Cvar_RegisterVariable(&r_transparent_sortmindist);
4361 Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4362 Cvar_RegisterVariable(&r_transparent_sortarraysize);
4363 Cvar_RegisterVariable(&r_texture_dds_load);
4364 Cvar_RegisterVariable(&r_texture_dds_save);
4365 Cvar_RegisterVariable(&r_textureunits);
4366 Cvar_RegisterVariable(&gl_combine);
4367 Cvar_RegisterVariable(&r_usedepthtextures);
4368 Cvar_RegisterVariable(&r_viewfbo);
4369 Cvar_RegisterVariable(&r_viewscale);
4370 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4371 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4372 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4373 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4374 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4375 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4376 Cvar_RegisterVariable(&r_glsl);
4377 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4378 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4379 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4380 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4381 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4382 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4383 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4384 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4385 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4386 Cvar_RegisterVariable(&r_glsl_postprocess);
4387 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4388 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4389 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4390 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4391 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4392 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4393 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4394 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4395 Cvar_RegisterVariable(&r_celshading);
4396 Cvar_RegisterVariable(&r_celoutlines);
4398 Cvar_RegisterVariable(&r_water);
4399 Cvar_RegisterVariable(&r_water_cameraentitiesonly);
4400 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4401 Cvar_RegisterVariable(&r_water_clippingplanebias);
4402 Cvar_RegisterVariable(&r_water_refractdistort);
4403 Cvar_RegisterVariable(&r_water_reflectdistort);
4404 Cvar_RegisterVariable(&r_water_scissormode);
4405 Cvar_RegisterVariable(&r_water_lowquality);
4406 Cvar_RegisterVariable(&r_water_hideplayer);
4407 Cvar_RegisterVariable(&r_water_fbo);
4409 Cvar_RegisterVariable(&r_lerpsprites);
4410 Cvar_RegisterVariable(&r_lerpmodels);
4411 Cvar_RegisterVariable(&r_lerplightstyles);
4412 Cvar_RegisterVariable(&r_waterscroll);
4413 Cvar_RegisterVariable(&r_bloom);
4414 Cvar_RegisterVariable(&r_bloom_colorscale);
4415 Cvar_RegisterVariable(&r_bloom_brighten);
4416 Cvar_RegisterVariable(&r_bloom_blur);
4417 Cvar_RegisterVariable(&r_bloom_resolution);
4418 Cvar_RegisterVariable(&r_bloom_colorexponent);
4419 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4420 Cvar_RegisterVariable(&r_bloom_scenebrightness);
4421 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4422 Cvar_RegisterVariable(&r_hdr_glowintensity);
4423 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4424 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4425 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4426 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4427 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4428 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4429 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4430 Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4431 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4432 Cvar_RegisterVariable(&developer_texturelogging);
4433 Cvar_RegisterVariable(&gl_lightmaps);
4434 Cvar_RegisterVariable(&r_test);
4435 Cvar_RegisterVariable(&r_batch_multidraw);
4436 Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4437 Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4438 Cvar_RegisterVariable(&r_glsl_skeletal);
4439 Cvar_RegisterVariable(&r_glsl_saturation);
4440 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4441 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4442 Cvar_RegisterVariable(&r_framedatasize);
4443 for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4444 Cvar_RegisterVariable(&r_buffermegs[i]);
4445 Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4446 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4447 Cvar_SetValue("r_fullbrights", 0);
4448 #ifdef DP_MOBILETOUCH
4449 // GLES devices have terrible depth precision in general, so...
4450 Cvar_SetValueQuick(&r_nearclip, 4);
4451 Cvar_SetValueQuick(&r_farclip_base, 4096);
4452 Cvar_SetValueQuick(&r_farclip_world, 0);
4453 Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
4455 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4458 void Render_Init(void)
4471 R_LightningBeams_Init();
4481 extern char *ENGINE_EXTENSIONS;
4484 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4485 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4486 gl_version = (const char *)qglGetString(GL_VERSION);
4487 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4491 if (!gl_platformextensions)
4492 gl_platformextensions = "";
4494 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4495 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4496 Con_Printf("GL_VERSION: %s\n", gl_version);
4497 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4498 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4500 VID_CheckExtensions();
4502 // LordHavoc: report supported extensions
4504 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4506 Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
4509 // clear to black (loading plaque will be seen over this)
4510 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4514 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4518 if (r_trippy.integer)
4520 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4522 p = r_refdef.view.frustum + i;
4527 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4531 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4535 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4539 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4543 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4547 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4551 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4555 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4563 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4567 if (r_trippy.integer)
4569 for (i = 0;i < numplanes;i++)
4576 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4580 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4584 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4588 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4592 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4596 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4600 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4604 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4612 //==================================================================================
4614 // LordHavoc: this stores temporary data used within the same frame
4616 typedef struct r_framedata_mem_s
4618 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4619 size_t size; // how much usable space
4620 size_t current; // how much space in use
4621 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4622 size_t wantedsize; // how much space was allocated
4623 unsigned char *data; // start of real data (16byte aligned)
4627 static r_framedata_mem_t *r_framedata_mem;
4629 void R_FrameData_Reset(void)
4631 while (r_framedata_mem)
4633 r_framedata_mem_t *next = r_framedata_mem->purge;
4634 Mem_Free(r_framedata_mem);
4635 r_framedata_mem = next;
4639 static void R_FrameData_Resize(qboolean mustgrow)
4642 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4643 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4644 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4646 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4647 newmem->wantedsize = wantedsize;
4648 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4649 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4650 newmem->current = 0;
4652 newmem->purge = r_framedata_mem;
4653 r_framedata_mem = newmem;
4657 void R_FrameData_NewFrame(void)
4659 R_FrameData_Resize(false);
4660 if (!r_framedata_mem)
4662 // if we ran out of space on the last frame, free the old memory now
4663 while (r_framedata_mem->purge)
4665 // repeatedly remove the second item in the list, leaving only head
4666 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4667 Mem_Free(r_framedata_mem->purge);
4668 r_framedata_mem->purge = next;
4670 // reset the current mem pointer
4671 r_framedata_mem->current = 0;
4672 r_framedata_mem->mark = 0;
4675 void *R_FrameData_Alloc(size_t size)
4680 // align to 16 byte boundary - the data pointer is already aligned, so we
4681 // only need to ensure the size of every allocation is also aligned
4682 size = (size + 15) & ~15;
4684 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4686 // emergency - we ran out of space, allocate more memory
4687 newvalue = bound(0.25f, r_framedatasize.value * 2.0f, 256.0f);
4688 // this might not be a growing it, but we'll allocate another buffer every time
4689 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4690 R_FrameData_Resize(true);
4693 data = r_framedata_mem->data + r_framedata_mem->current;
4694 r_framedata_mem->current += size;
4696 // count the usage for stats
4697 r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4698 r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4700 return (void *)data;
4703 void *R_FrameData_Store(size_t size, void *data)
4705 void *d = R_FrameData_Alloc(size);
4707 memcpy(d, data, size);
4711 void R_FrameData_SetMark(void)
4713 if (!r_framedata_mem)
4715 r_framedata_mem->mark = r_framedata_mem->current;
4718 void R_FrameData_ReturnToMark(void)
4720 if (!r_framedata_mem)
4722 r_framedata_mem->current = r_framedata_mem->mark;
4725 //==================================================================================
4727 // avoid reusing the same buffer objects on consecutive frames
4728 #define R_BUFFERDATA_CYCLE 3
4730 typedef struct r_bufferdata_buffer_s
4732 struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4733 size_t size; // how much usable space
4734 size_t current; // how much space in use
4735 r_meshbuffer_t *buffer; // the buffer itself
4737 r_bufferdata_buffer_t;
4739 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4740 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4742 /// frees all dynamic buffers
4743 void R_BufferData_Reset(void)
4746 r_bufferdata_buffer_t **p, *mem;
4747 for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4749 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4752 p = &r_bufferdata_buffer[cycle][type];
4758 R_Mesh_DestroyMeshBuffer(mem->buffer);
4765 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4766 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4768 r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4770 float newvalue = r_buffermegs[type].value;
4772 // increase the cvar if we have to (but only if we already have a mem)
4773 if (mustgrow && mem)
4775 newvalue = bound(0.25f, newvalue, 256.0f);
4776 while (newvalue * 1024*1024 < minsize)
4779 // clamp the cvar to valid range
4780 newvalue = bound(0.25f, newvalue, 256.0f);
4781 if (r_buffermegs[type].value != newvalue)
4782 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4784 // calculate size in bytes
4785 size = (size_t)(newvalue * 1024*1024);
4786 size = bound(131072, size, 256*1024*1024);
4788 // allocate a new buffer if the size is different (purge old one later)
4789 // or if we were told we must grow the buffer
4790 if (!mem || mem->size != size || mustgrow)
4792 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4795 if (type == R_BUFFERDATA_VERTEX)
4796 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4797 else if (type == R_BUFFERDATA_INDEX16)
4798 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4799 else if (type == R_BUFFERDATA_INDEX32)
4800 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4801 else if (type == R_BUFFERDATA_UNIFORM)
4802 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4803 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4804 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4808 void R_BufferData_NewFrame(void)
4811 r_bufferdata_buffer_t **p, *mem;
4812 // cycle to the next frame's buffers
4813 r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4814 // if we ran out of space on the last time we used these buffers, free the old memory now
4815 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4817 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4819 R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4820 // free all but the head buffer, this is how we recycle obsolete
4821 // buffers after they are no longer in use
4822 p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4828 R_Mesh_DestroyMeshBuffer(mem->buffer);
4831 // reset the current offset
4832 r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4837 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4839 r_bufferdata_buffer_t *mem;
4843 *returnbufferoffset = 0;
4845 // align size to a byte boundary appropriate for the buffer type, this
4846 // makes all allocations have aligned start offsets
4847 if (type == R_BUFFERDATA_UNIFORM)
4848 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4850 padsize = (datasize + 15) & ~15;
4852 // if we ran out of space in this buffer we must allocate a new one
4853 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)
4854 R_BufferData_Resize(type, true, padsize);
4856 // if the resize did not give us enough memory, fail
4857 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)
4858 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4860 mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4861 offset = (int)mem->current;
4862 mem->current += padsize;
4864 // upload the data to the buffer at the chosen offset
4866 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4867 R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4869 // count the usage for stats
4870 r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4871 r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4873 // return the buffer offset
4874 *returnbufferoffset = offset;
4879 //==================================================================================
4881 // LordHavoc: animcache originally written by Echon, rewritten since then
4884 * Animation cache prevents re-generating mesh data for an animated model
4885 * multiple times in one frame for lighting, shadowing, reflections, etc.
4888 void R_AnimCache_Free(void)
4892 void R_AnimCache_ClearCache(void)
4895 entity_render_t *ent;
4897 for (i = 0;i < r_refdef.scene.numentities;i++)
4899 ent = r_refdef.scene.entities[i];
4900 ent->animcache_vertex3f = NULL;
4901 ent->animcache_vertex3f_vertexbuffer = NULL;
4902 ent->animcache_vertex3f_bufferoffset = 0;
4903 ent->animcache_normal3f = NULL;
4904 ent->animcache_normal3f_vertexbuffer = NULL;
4905 ent->animcache_normal3f_bufferoffset = 0;
4906 ent->animcache_svector3f = NULL;
4907 ent->animcache_svector3f_vertexbuffer = NULL;
4908 ent->animcache_svector3f_bufferoffset = 0;
4909 ent->animcache_tvector3f = NULL;
4910 ent->animcache_tvector3f_vertexbuffer = NULL;
4911 ent->animcache_tvector3f_bufferoffset = 0;
4912 ent->animcache_vertexmesh = NULL;
4913 ent->animcache_vertexmesh_vertexbuffer = NULL;
4914 ent->animcache_vertexmesh_bufferoffset = 0;
4915 ent->animcache_skeletaltransform3x4 = NULL;
4916 ent->animcache_skeletaltransform3x4buffer = NULL;
4917 ent->animcache_skeletaltransform3x4offset = 0;
4918 ent->animcache_skeletaltransform3x4size = 0;
4922 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4926 // check if we need the meshbuffers
4927 if (!vid.useinterleavedarrays)
4930 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4931 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4932 // TODO: upload vertexbuffer?
4933 if (ent->animcache_vertexmesh)
4935 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4936 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4937 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4938 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4939 for (i = 0;i < numvertices;i++)
4940 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4941 if (ent->animcache_svector3f)
4942 for (i = 0;i < numvertices;i++)
4943 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4944 if (ent->animcache_tvector3f)
4945 for (i = 0;i < numvertices;i++)
4946 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4947 if (ent->animcache_normal3f)
4948 for (i = 0;i < numvertices;i++)
4949 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4953 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4955 dp_model_t *model = ent->model;
4958 // see if this ent is worth caching
4959 if (!model || !model->Draw || !model->AnimateVertices)
4961 // nothing to cache if it contains no animations and has no skeleton
4962 if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4964 // see if it is already cached for gpuskeletal
4965 if (ent->animcache_skeletaltransform3x4)
4967 // see if it is already cached as a mesh
4968 if (ent->animcache_vertex3f)
4970 // check if we need to add normals or tangents
4971 if (ent->animcache_normal3f)
4972 wantnormals = false;
4973 if (ent->animcache_svector3f)
4974 wanttangents = false;
4975 if (!wantnormals && !wanttangents)
4979 // check which kind of cache we need to generate
4980 if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4982 // cache the skeleton so the vertex shader can use it
4983 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
4984 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
4985 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
4986 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4987 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4);
4988 // note: this can fail if the buffer is at the grow limit
4989 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
4990 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
4992 else if (ent->animcache_vertex3f)
4994 // mesh was already cached but we may need to add normals/tangents
4995 // (this only happens with multiple views, reflections, cameras, etc)
4996 if (wantnormals || wanttangents)
4998 numvertices = model->surfmesh.num_vertices;
5000 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5003 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5004 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5006 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
5007 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5008 r_refdef.stats[r_stat_animcache_shade_count] += 1;
5009 r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5010 r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5015 // generate mesh cache
5016 numvertices = model->surfmesh.num_vertices;
5017 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5019 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5022 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5023 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5025 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
5026 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5027 if (wantnormals || wanttangents)
5029 r_refdef.stats[r_stat_animcache_shade_count] += 1;
5030 r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5031 r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5033 r_refdef.stats[r_stat_animcache_shape_count] += 1;
5034 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
5035 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
5040 void R_AnimCache_CacheVisibleEntities(void)
5043 qboolean wantnormals = true;
5044 qboolean wanttangents = !r_showsurfaces.integer;
5046 switch(vid.renderpath)
5048 case RENDERPATH_GL20:
5049 case RENDERPATH_D3D9:
5050 case RENDERPATH_D3D10:
5051 case RENDERPATH_D3D11:
5052 case RENDERPATH_GLES2:
5054 case RENDERPATH_GL11:
5055 case RENDERPATH_GL13:
5056 case RENDERPATH_GLES1:
5057 wanttangents = false;
5059 case RENDERPATH_SOFT:
5063 if (r_shownormals.integer)
5064 wanttangents = wantnormals = true;
5066 // TODO: thread this
5067 // NOTE: R_PrepareRTLights() also caches entities
5069 for (i = 0;i < r_refdef.scene.numentities;i++)
5070 if (r_refdef.viewcache.entityvisible[i])
5071 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5074 //==================================================================================
5076 extern cvar_t r_overheadsprites_pushback;
5078 static void R_View_UpdateEntityLighting (void)
5081 entity_render_t *ent;
5082 vec3_t tempdiffusenormal, avg;
5083 vec_t f, fa, fd, fdd;
5084 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
5086 for (i = 0;i < r_refdef.scene.numentities;i++)
5088 ent = r_refdef.scene.entities[i];
5090 // skip unseen models
5091 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
5095 if (ent->model && ent->model == cl.worldmodel)
5097 // TODO: use modellight for r_ambient settings on world?
5098 VectorSet(ent->modellight_ambient, 0, 0, 0);
5099 VectorSet(ent->modellight_diffuse, 0, 0, 0);
5100 VectorSet(ent->modellight_lightdir, 0, 0, 1);
5104 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
5106 // aleady updated by CSQC
5107 // TODO: force modellight on BSP models in this case?
5108 VectorCopy(ent->modellight_lightdir, tempdiffusenormal);
5112 // fetch the lighting from the worldmodel data
5113 VectorClear(ent->modellight_ambient);
5114 VectorClear(ent->modellight_diffuse);
5115 VectorClear(tempdiffusenormal);
5116 if (ent->flags & RENDER_LIGHT)
5119 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5121 // complete lightning for lit sprites
5122 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
5123 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
5125 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
5126 org[2] = org[2] + r_overheadsprites_pushback.value;
5127 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5130 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
5132 if(ent->flags & RENDER_EQUALIZE)
5134 // first fix up ambient lighting...
5135 if(r_equalize_entities_minambient.value > 0)
5137 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5140 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
5141 if(fa < r_equalize_entities_minambient.value * fd)
5144 // fa'/fd' = minambient
5145 // fa'+0.25*fd' = fa+0.25*fd
5147 // fa' = fd' * minambient
5148 // fd'*(0.25+minambient) = fa+0.25*fd
5150 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
5151 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
5153 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
5154 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
5155 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
5156 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
5161 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
5163 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
5164 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5168 // adjust brightness and saturation to target
5169 avg[0] = avg[1] = avg[2] = fa / f;
5170 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
5171 avg[0] = avg[1] = avg[2] = fd / f;
5172 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
5178 VectorSet(ent->modellight_ambient, 1, 1, 1);
5181 // move the light direction into modelspace coordinates for lighting code
5182 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
5183 if(VectorLength2(ent->modellight_lightdir) == 0)
5184 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
5185 VectorNormalize(ent->modellight_lightdir);
5189 #define MAX_LINEOFSIGHTTRACES 64
5191 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5194 vec3_t boxmins, boxmaxs;
5197 dp_model_t *model = r_refdef.scene.worldmodel;
5199 if (!model || !model->brush.TraceLineOfSight)
5202 // expand the box a little
5203 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
5204 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
5205 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
5206 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
5207 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
5208 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
5210 // return true if eye is inside enlarged box
5211 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
5215 VectorCopy(eye, start);
5216 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
5217 if (model->brush.TraceLineOfSight(model, start, end))
5220 // try various random positions
5221 for (i = 0;i < numsamples;i++)
5223 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5224 if (model->brush.TraceLineOfSight(model, start, end))
5232 static void R_View_UpdateEntityVisible (void)
5237 entity_render_t *ent;
5239 if (r_refdef.envmap || r_fb.water.hideplayer)
5240 renderimask = RENDER_EXTERIORMODEL | RENDER_VIEWMODEL;
5241 else if (chase_active.integer || r_fb.water.renderingscene)
5242 renderimask = RENDER_VIEWMODEL;
5244 renderimask = RENDER_EXTERIORMODEL;
5245 if (!r_drawviewmodel.integer)
5246 renderimask |= RENDER_VIEWMODEL;
5247 if (!r_drawexteriormodel.integer)
5248 renderimask |= RENDER_EXTERIORMODEL;
5249 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5250 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5252 // worldmodel can check visibility
5253 for (i = 0;i < r_refdef.scene.numentities;i++)
5255 ent = r_refdef.scene.entities[i];
5256 if (!(ent->flags & renderimask))
5257 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)))
5258 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))
5259 r_refdef.viewcache.entityvisible[i] = true;
5264 // no worldmodel or it can't check visibility
5265 for (i = 0;i < r_refdef.scene.numentities;i++)
5267 ent = r_refdef.scene.entities[i];
5268 if (!(ent->flags & renderimask))
5269 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)))
5270 r_refdef.viewcache.entityvisible[i] = true;
5273 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
5274 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
5276 for (i = 0;i < r_refdef.scene.numentities;i++)
5278 if (!r_refdef.viewcache.entityvisible[i])
5280 ent = r_refdef.scene.entities[i];
5281 if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5283 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
5285 continue; // temp entities do pvs only
5286 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5287 ent->last_trace_visibility = realtime;
5288 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5289 r_refdef.viewcache.entityvisible[i] = 0;
5295 /// only used if skyrendermasked, and normally returns false
5296 static int R_DrawBrushModelsSky (void)
5299 entity_render_t *ent;
5302 for (i = 0;i < r_refdef.scene.numentities;i++)
5304 if (!r_refdef.viewcache.entityvisible[i])
5306 ent = r_refdef.scene.entities[i];
5307 if (!ent->model || !ent->model->DrawSky)
5309 ent->model->DrawSky(ent);
5315 static void R_DrawNoModel(entity_render_t *ent);
5316 static void R_DrawModels(void)
5319 entity_render_t *ent;
5321 for (i = 0;i < r_refdef.scene.numentities;i++)
5323 if (!r_refdef.viewcache.entityvisible[i])
5325 ent = r_refdef.scene.entities[i];
5326 r_refdef.stats[r_stat_entities]++;
5328 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5331 Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5332 Con_Printf("R_DrawModels\n");
5333 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]);
5334 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);
5335 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);
5338 if (ent->model && ent->model->Draw != NULL)
5339 ent->model->Draw(ent);
5345 static void R_DrawModelsDepth(void)
5348 entity_render_t *ent;
5350 for (i = 0;i < r_refdef.scene.numentities;i++)
5352 if (!r_refdef.viewcache.entityvisible[i])
5354 ent = r_refdef.scene.entities[i];
5355 if (ent->model && ent->model->DrawDepth != NULL)
5356 ent->model->DrawDepth(ent);
5360 static void R_DrawModelsDebug(void)
5363 entity_render_t *ent;
5365 for (i = 0;i < r_refdef.scene.numentities;i++)
5367 if (!r_refdef.viewcache.entityvisible[i])
5369 ent = r_refdef.scene.entities[i];
5370 if (ent->model && ent->model->DrawDebug != NULL)
5371 ent->model->DrawDebug(ent);
5375 static void R_DrawModelsAddWaterPlanes(void)
5378 entity_render_t *ent;
5380 for (i = 0;i < r_refdef.scene.numentities;i++)
5382 if (!r_refdef.viewcache.entityvisible[i])
5384 ent = r_refdef.scene.entities[i];
5385 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5386 ent->model->DrawAddWaterPlanes(ent);
5390 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}};
5392 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5394 if (r_hdr_irisadaptation.integer)
5399 vec3_t diffusenormal;
5401 vec_t brightness = 0.0f;
5406 VectorCopy(r_refdef.view.forward, forward);
5407 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5409 p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5410 p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5411 p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5412 R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5413 d = DotProduct(forward, diffusenormal);
5414 brightness += VectorLength(ambient);
5416 brightness += d * VectorLength(diffuse);
5418 brightness *= 1.0f / c;
5419 brightness += 0.00001f; // make sure it's never zero
5420 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5421 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5422 current = r_hdr_irisadaptation_value.value;
5424 current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5425 else if (current > goal)
5426 current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5427 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5428 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5430 else if (r_hdr_irisadaptation_value.value != 1.0f)
5431 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5434 static void R_View_SetFrustum(const int *scissor)
5437 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5438 vec3_t forward, left, up, origin, v;
5442 // flipped x coordinates (because x points left here)
5443 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5444 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5446 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5447 switch(vid.renderpath)
5449 case RENDERPATH_D3D9:
5450 case RENDERPATH_D3D10:
5451 case RENDERPATH_D3D11:
5452 // non-flipped y coordinates
5453 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5454 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5456 case RENDERPATH_SOFT:
5457 case RENDERPATH_GL11:
5458 case RENDERPATH_GL13:
5459 case RENDERPATH_GL20:
5460 case RENDERPATH_GLES1:
5461 case RENDERPATH_GLES2:
5462 // non-flipped y coordinates
5463 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5464 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5469 // we can't trust r_refdef.view.forward and friends in reflected scenes
5470 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5473 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5474 r_refdef.view.frustum[0].normal[1] = 0 - 0;
5475 r_refdef.view.frustum[0].normal[2] = -1 - 0;
5476 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5477 r_refdef.view.frustum[1].normal[1] = 0 + 0;
5478 r_refdef.view.frustum[1].normal[2] = -1 + 0;
5479 r_refdef.view.frustum[2].normal[0] = 0 - 0;
5480 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5481 r_refdef.view.frustum[2].normal[2] = -1 - 0;
5482 r_refdef.view.frustum[3].normal[0] = 0 + 0;
5483 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5484 r_refdef.view.frustum[3].normal[2] = -1 + 0;
5488 zNear = r_refdef.nearclip;
5489 nudge = 1.0 - 1.0 / (1<<23);
5490 r_refdef.view.frustum[4].normal[0] = 0 - 0;
5491 r_refdef.view.frustum[4].normal[1] = 0 - 0;
5492 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5493 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5494 r_refdef.view.frustum[5].normal[0] = 0 + 0;
5495 r_refdef.view.frustum[5].normal[1] = 0 + 0;
5496 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5497 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5503 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5504 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5505 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5506 r_refdef.view.frustum[0].dist = m[15] - m[12];
5508 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5509 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5510 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5511 r_refdef.view.frustum[1].dist = m[15] + m[12];
5513 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5514 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5515 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5516 r_refdef.view.frustum[2].dist = m[15] - m[13];
5518 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5519 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5520 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5521 r_refdef.view.frustum[3].dist = m[15] + m[13];
5523 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5524 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5525 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5526 r_refdef.view.frustum[4].dist = m[15] - m[14];
5528 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5529 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5530 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5531 r_refdef.view.frustum[5].dist = m[15] + m[14];
5534 if (r_refdef.view.useperspective)
5536 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5537 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]);
5538 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]);
5539 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]);
5540 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]);
5542 // then the normals from the corners relative to origin
5543 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5544 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5545 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5546 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5548 // in a NORMAL view, forward cross left == up
5549 // in a REFLECTED view, forward cross left == down
5550 // so our cross products above need to be adjusted for a left handed coordinate system
5551 CrossProduct(forward, left, v);
5552 if(DotProduct(v, up) < 0)
5554 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5555 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5556 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5557 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5560 // Leaving those out was a mistake, those were in the old code, and they
5561 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5562 // I couldn't reproduce it after adding those normalizations. --blub
5563 VectorNormalize(r_refdef.view.frustum[0].normal);
5564 VectorNormalize(r_refdef.view.frustum[1].normal);
5565 VectorNormalize(r_refdef.view.frustum[2].normal);
5566 VectorNormalize(r_refdef.view.frustum[3].normal);
5568 // make the corners absolute
5569 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5570 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5571 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5572 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5575 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5577 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5578 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5579 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5580 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5581 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5585 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5586 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5587 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5588 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5589 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5590 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5591 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5592 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5593 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5594 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5596 r_refdef.view.numfrustumplanes = 5;
5598 if (r_refdef.view.useclipplane)
5600 r_refdef.view.numfrustumplanes = 6;
5601 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5604 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5605 PlaneClassify(r_refdef.view.frustum + i);
5607 // LordHavoc: note to all quake engine coders, Quake had a special case
5608 // for 90 degrees which assumed a square view (wrong), so I removed it,
5609 // Quake2 has it disabled as well.
5611 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5612 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5613 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5614 //PlaneClassify(&frustum[0]);
5616 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5617 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5618 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5619 //PlaneClassify(&frustum[1]);
5621 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5622 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5623 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5624 //PlaneClassify(&frustum[2]);
5626 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5627 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5628 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5629 //PlaneClassify(&frustum[3]);
5632 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5633 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5634 //PlaneClassify(&frustum[4]);
5637 static void R_View_UpdateWithScissor(const int *myscissor)
5639 R_Main_ResizeViewCache();
5640 R_View_SetFrustum(myscissor);
5641 R_View_WorldVisibility(r_refdef.view.useclipplane);
5642 R_View_UpdateEntityVisible();
5643 R_View_UpdateEntityLighting();
5646 static void R_View_Update(void)
5648 R_Main_ResizeViewCache();
5649 R_View_SetFrustum(NULL);
5650 R_View_WorldVisibility(r_refdef.view.useclipplane);
5651 R_View_UpdateEntityVisible();
5652 R_View_UpdateEntityLighting();
5655 float viewscalefpsadjusted = 1.0f;
5657 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5659 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5660 scale = bound(0.03125f, scale, 1.0f);
5661 *outwidth = (int)ceil(width * scale);
5662 *outheight = (int)ceil(height * scale);
5665 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5667 const float *customclipplane = NULL;
5669 int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5670 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5672 // LordHavoc: couldn't figure out how to make this approach the
5673 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5674 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5675 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5676 dist = r_refdef.view.clipplane.dist;
5677 plane[0] = r_refdef.view.clipplane.normal[0];
5678 plane[1] = r_refdef.view.clipplane.normal[1];
5679 plane[2] = r_refdef.view.clipplane.normal[2];
5681 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5684 //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5685 rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5687 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5688 if (!r_refdef.view.useperspective)
5689 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);
5690 else if (vid.stencil && r_useinfinitefarclip.integer)
5691 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);
5693 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);
5694 R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5695 R_SetViewport(&r_refdef.view.viewport);
5696 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5698 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5699 float screenplane[4];
5700 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5701 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5702 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5703 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5704 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5708 void R_EntityMatrix(const matrix4x4_t *matrix)
5710 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5712 gl_modelmatrixchanged = false;
5713 gl_modelmatrix = *matrix;
5714 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5715 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5716 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5717 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5719 switch(vid.renderpath)
5721 case RENDERPATH_D3D9:
5723 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5724 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5727 case RENDERPATH_D3D10:
5728 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5730 case RENDERPATH_D3D11:
5731 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5733 case RENDERPATH_GL11:
5734 case RENDERPATH_GL13:
5735 case RENDERPATH_GLES1:
5737 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5740 case RENDERPATH_SOFT:
5741 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5742 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5744 case RENDERPATH_GL20:
5745 case RENDERPATH_GLES2:
5746 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5747 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5753 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5755 r_viewport_t viewport;
5759 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5760 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);
5761 R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5762 R_SetViewport(&viewport);
5763 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5764 GL_Color(1, 1, 1, 1);
5765 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5766 GL_BlendFunc(GL_ONE, GL_ZERO);
5767 GL_ScissorTest(false);
5768 GL_DepthMask(false);
5769 GL_DepthRange(0, 1);
5770 GL_DepthTest(false);
5771 GL_DepthFunc(GL_LEQUAL);
5772 R_EntityMatrix(&identitymatrix);
5773 R_Mesh_ResetTextureState();
5774 GL_PolygonOffset(0, 0);
5775 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5776 switch(vid.renderpath)
5778 case RENDERPATH_GL11:
5779 case RENDERPATH_GL13:
5780 case RENDERPATH_GL20:
5781 case RENDERPATH_GLES1:
5782 case RENDERPATH_GLES2:
5783 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5785 case RENDERPATH_D3D9:
5786 case RENDERPATH_D3D10:
5787 case RENDERPATH_D3D11:
5788 case RENDERPATH_SOFT:
5791 GL_CullFace(GL_NONE);
5796 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5800 R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5803 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5807 R_SetupView(true, fbo, depthtexture, colortexture);
5808 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5809 GL_Color(1, 1, 1, 1);
5810 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5811 GL_BlendFunc(GL_ONE, GL_ZERO);
5812 GL_ScissorTest(true);
5814 GL_DepthRange(0, 1);
5816 GL_DepthFunc(GL_LEQUAL);
5817 R_EntityMatrix(&identitymatrix);
5818 R_Mesh_ResetTextureState();
5819 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5820 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5821 switch(vid.renderpath)
5823 case RENDERPATH_GL11:
5824 case RENDERPATH_GL13:
5825 case RENDERPATH_GL20:
5826 case RENDERPATH_GLES1:
5827 case RENDERPATH_GLES2:
5828 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5830 case RENDERPATH_D3D9:
5831 case RENDERPATH_D3D10:
5832 case RENDERPATH_D3D11:
5833 case RENDERPATH_SOFT:
5836 GL_CullFace(r_refdef.view.cullface_back);
5841 R_RenderView_UpdateViewVectors
5844 void R_RenderView_UpdateViewVectors(void)
5846 // break apart the view matrix into vectors for various purposes
5847 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5848 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5849 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5850 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5851 // make an inverted copy of the view matrix for tracking sprites
5852 Matrix4x4_Invert_Full(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5855 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5856 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5858 static void R_Water_StartFrame(void)
5861 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5862 r_waterstate_waterplane_t *p;
5863 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;
5865 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5868 switch(vid.renderpath)
5870 case RENDERPATH_GL20:
5871 case RENDERPATH_D3D9:
5872 case RENDERPATH_D3D10:
5873 case RENDERPATH_D3D11:
5874 case RENDERPATH_SOFT:
5875 case RENDERPATH_GLES2:
5877 case RENDERPATH_GL11:
5878 case RENDERPATH_GL13:
5879 case RENDERPATH_GLES1:
5883 // set waterwidth and waterheight to the water resolution that will be
5884 // used (often less than the screen resolution for faster rendering)
5885 R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5887 // calculate desired texture sizes
5888 // can't use water if the card does not support the texture size
5889 if (!r_water.integer || r_showsurfaces.integer)
5890 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5891 else if (vid.support.arb_texture_non_power_of_two)
5893 texturewidth = waterwidth;
5894 textureheight = waterheight;
5895 camerawidth = waterwidth;
5896 cameraheight = waterheight;
5900 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5901 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5902 for (camerawidth = 1;camerawidth * 2 <= waterwidth ;camerawidth *= 2);
5903 for (cameraheight = 1;cameraheight * 2 <= waterheight;cameraheight *= 2);
5906 // allocate textures as needed
5907 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))
5909 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5910 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5912 if (p->texture_refraction)
5913 R_FreeTexture(p->texture_refraction);
5914 p->texture_refraction = NULL;
5915 if (p->fbo_refraction)
5916 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5917 p->fbo_refraction = 0;
5918 if (p->texture_reflection)
5919 R_FreeTexture(p->texture_reflection);
5920 p->texture_reflection = NULL;
5921 if (p->fbo_reflection)
5922 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5923 p->fbo_reflection = 0;
5924 if (p->texture_camera)
5925 R_FreeTexture(p->texture_camera);
5926 p->texture_camera = NULL;
5928 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5931 memset(&r_fb.water, 0, sizeof(r_fb.water));
5932 r_fb.water.texturewidth = texturewidth;
5933 r_fb.water.textureheight = textureheight;
5934 r_fb.water.camerawidth = camerawidth;
5935 r_fb.water.cameraheight = cameraheight;
5938 if (r_fb.water.texturewidth)
5940 int scaledwidth, scaledheight;
5942 r_fb.water.enabled = true;
5944 // water resolution is usually reduced
5945 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5946 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5947 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5949 // set up variables that will be used in shader setup
5950 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5951 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5952 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5953 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5956 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5957 r_fb.water.numwaterplanes = 0;
5960 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5962 int planeindex, bestplaneindex, vertexindex;
5963 vec3_t mins, maxs, normal, center, v, n;
5964 vec_t planescore, bestplanescore;
5966 r_waterstate_waterplane_t *p;
5967 texture_t *t = R_GetCurrentTexture(surface->texture);
5969 rsurface.texture = t;
5970 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5971 // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5972 if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5974 // average the vertex normals, find the surface bounds (after deformvertexes)
5975 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5976 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5977 VectorCopy(n, normal);
5978 VectorCopy(v, mins);
5979 VectorCopy(v, maxs);
5980 for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5982 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5983 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5984 VectorAdd(normal, n, normal);
5985 mins[0] = min(mins[0], v[0]);
5986 mins[1] = min(mins[1], v[1]);
5987 mins[2] = min(mins[2], v[2]);
5988 maxs[0] = max(maxs[0], v[0]);
5989 maxs[1] = max(maxs[1], v[1]);
5990 maxs[2] = max(maxs[2], v[2]);
5992 VectorNormalize(normal);
5993 VectorMAM(0.5f, mins, 0.5f, maxs, center);
5995 VectorCopy(normal, plane.normal);
5996 VectorNormalize(plane.normal);
5997 plane.dist = DotProduct(center, plane.normal);
5998 PlaneClassify(&plane);
5999 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
6001 // skip backfaces (except if nocullface is set)
6002 // if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
6004 VectorNegate(plane.normal, plane.normal);
6006 PlaneClassify(&plane);
6010 // find a matching plane if there is one
6011 bestplaneindex = -1;
6012 bestplanescore = 1048576.0f;
6013 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6015 if(p->camera_entity == t->camera_entity)
6017 planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
6018 if (bestplaneindex < 0 || bestplanescore > planescore)
6020 bestplaneindex = planeindex;
6021 bestplanescore = planescore;
6025 planeindex = bestplaneindex;
6027 // if this surface does not fit any known plane rendered this frame, add one
6028 if (planeindex < 0 || bestplanescore > 0.001f)
6030 if (r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
6032 // store the new plane
6033 planeindex = r_fb.water.numwaterplanes++;
6034 p = r_fb.water.waterplanes + planeindex;
6036 // clear materialflags and pvs
6037 p->materialflags = 0;
6038 p->pvsvalid = false;
6039 p->camera_entity = t->camera_entity;
6040 VectorCopy(mins, p->mins);
6041 VectorCopy(maxs, p->maxs);
6045 // We're totally screwed.
6051 // merge mins/maxs when we're adding this surface to the plane
6052 p = r_fb.water.waterplanes + planeindex;
6053 p->mins[0] = min(p->mins[0], mins[0]);
6054 p->mins[1] = min(p->mins[1], mins[1]);
6055 p->mins[2] = min(p->mins[2], mins[2]);
6056 p->maxs[0] = max(p->maxs[0], maxs[0]);
6057 p->maxs[1] = max(p->maxs[1], maxs[1]);
6058 p->maxs[2] = max(p->maxs[2], maxs[2]);
6060 // merge this surface's materialflags into the waterplane
6061 p->materialflags |= t->currentmaterialflags;
6062 if(!(p->materialflags & MATERIALFLAG_CAMERA))
6064 // merge this surface's PVS into the waterplane
6065 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6066 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6068 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6074 extern cvar_t r_drawparticles;
6075 extern cvar_t r_drawdecals;
6077 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6080 r_refdef_view_t originalview;
6081 r_refdef_view_t myview;
6082 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;
6083 r_waterstate_waterplane_t *p;
6085 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;
6088 originalview = r_refdef.view;
6090 // lowquality hack, temporarily shut down some cvars and restore afterwards
6091 qualityreduction = r_water_lowquality.integer;
6092 if (qualityreduction > 0)
6094 if (qualityreduction >= 1)
6096 old_r_shadows = r_shadows.integer;
6097 old_r_worldrtlight = r_shadow_realtime_world.integer;
6098 old_r_dlight = r_shadow_realtime_dlight.integer;
6099 Cvar_SetValueQuick(&r_shadows, 0);
6100 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6101 Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6103 if (qualityreduction >= 2)
6105 old_r_dynamic = r_dynamic.integer;
6106 old_r_particles = r_drawparticles.integer;
6107 old_r_decals = r_drawdecals.integer;
6108 Cvar_SetValueQuick(&r_dynamic, 0);
6109 Cvar_SetValueQuick(&r_drawparticles, 0);
6110 Cvar_SetValueQuick(&r_drawdecals, 0);
6114 // make sure enough textures are allocated
6115 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6117 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6119 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6121 if (!p->texture_refraction)
6122 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);
6123 if (!p->texture_refraction)
6127 if (r_fb.water.depthtexture == NULL)
6128 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6129 if (p->fbo_refraction == 0)
6130 p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6133 else if (p->materialflags & MATERIALFLAG_CAMERA)
6135 if (!p->texture_camera)
6136 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);
6137 if (!p->texture_camera)
6141 if (r_fb.water.depthtexture == NULL)
6142 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6143 if (p->fbo_camera == 0)
6144 p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6148 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6150 if (!p->texture_reflection)
6151 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);
6152 if (!p->texture_reflection)
6156 if (r_fb.water.depthtexture == NULL)
6157 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6158 if (p->fbo_reflection == 0)
6159 p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6165 r_refdef.view = originalview;
6166 r_refdef.view.showdebug = false;
6167 r_refdef.view.width = r_fb.water.waterwidth;
6168 r_refdef.view.height = r_fb.water.waterheight;
6169 r_refdef.view.useclipplane = true;
6170 myview = r_refdef.view;
6171 r_fb.water.renderingscene = true;
6172 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6174 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6176 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6178 r_refdef.view = myview;
6179 if(r_water_scissormode.integer)
6181 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6182 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6183 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6186 // render reflected scene and copy into texture
6187 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6188 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6189 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6190 r_refdef.view.clipplane = p->plane;
6191 // reverse the cullface settings for this render
6192 r_refdef.view.cullface_front = GL_FRONT;
6193 r_refdef.view.cullface_back = GL_BACK;
6194 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6196 r_refdef.view.usecustompvs = true;
6198 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6200 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6203 r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
6204 R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6205 R_ClearScreen(r_refdef.fogenabled);
6206 if(r_water_scissormode.integer & 2)
6207 R_View_UpdateWithScissor(myscissor);
6210 R_AnimCache_CacheVisibleEntities();
6211 if(r_water_scissormode.integer & 1)
6212 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6213 R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6215 if (!p->fbo_reflection)
6216 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);
6217 r_fb.water.hideplayer = false;
6220 // render the normal view scene and copy into texture
6221 // (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)
6222 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6224 r_refdef.view = myview;
6225 if(r_water_scissormode.integer)
6227 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6228 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6229 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6232 r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
6234 r_refdef.view.clipplane = p->plane;
6235 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6236 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6238 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6240 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6241 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6242 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6243 R_RenderView_UpdateViewVectors();
6244 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6246 r_refdef.view.usecustompvs = true;
6247 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);
6251 PlaneClassify(&r_refdef.view.clipplane);
6253 R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6254 R_ClearScreen(r_refdef.fogenabled);
6255 if(r_water_scissormode.integer & 2)
6256 R_View_UpdateWithScissor(myscissor);
6259 R_AnimCache_CacheVisibleEntities();
6260 if(r_water_scissormode.integer & 1)
6261 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6262 R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6264 if (!p->fbo_refraction)
6265 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);
6266 r_fb.water.hideplayer = false;
6268 else if (p->materialflags & MATERIALFLAG_CAMERA)
6270 r_refdef.view = myview;
6272 r_refdef.view.clipplane = p->plane;
6273 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6274 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6276 r_refdef.view.width = r_fb.water.camerawidth;
6277 r_refdef.view.height = r_fb.water.cameraheight;
6278 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6279 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6280 r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6281 r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6283 if(p->camera_entity)
6285 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6286 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6289 // note: all of the view is used for displaying... so
6290 // there is no use in scissoring
6292 // reverse the cullface settings for this render
6293 r_refdef.view.cullface_front = GL_FRONT;
6294 r_refdef.view.cullface_back = GL_BACK;
6295 // also reverse the view matrix
6296 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
6297 R_RenderView_UpdateViewVectors();
6298 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6300 r_refdef.view.usecustompvs = true;
6301 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);
6304 // camera needs no clipplane
6305 r_refdef.view.useclipplane = false;
6307 PlaneClassify(&r_refdef.view.clipplane);
6309 r_fb.water.hideplayer = false;
6311 R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6312 R_ClearScreen(r_refdef.fogenabled);
6314 R_AnimCache_CacheVisibleEntities();
6315 R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6318 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);
6319 r_fb.water.hideplayer = false;
6323 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6324 r_fb.water.renderingscene = false;
6325 r_refdef.view = originalview;
6326 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6327 if (!r_fb.water.depthtexture)
6328 R_ClearScreen(r_refdef.fogenabled);
6330 R_AnimCache_CacheVisibleEntities();
6333 r_refdef.view = originalview;
6334 r_fb.water.renderingscene = false;
6335 Cvar_SetValueQuick(&r_water, 0);
6336 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
6338 // lowquality hack, restore cvars
6339 if (qualityreduction > 0)
6341 if (qualityreduction >= 1)
6343 Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6344 Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6345 Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6347 if (qualityreduction >= 2)
6349 Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6350 Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6351 Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6356 static void R_Bloom_StartFrame(void)
6359 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6360 int viewwidth, viewheight;
6361 qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6362 textype_t textype = TEXTYPE_COLORBUFFER;
6364 switch (vid.renderpath)
6366 case RENDERPATH_GL20:
6367 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6368 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6370 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6371 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6374 case RENDERPATH_GL11:
6375 case RENDERPATH_GL13:
6376 case RENDERPATH_GLES1:
6377 case RENDERPATH_GLES2:
6378 case RENDERPATH_D3D9:
6379 case RENDERPATH_D3D10:
6380 case RENDERPATH_D3D11:
6381 r_fb.usedepthtextures = false;
6383 case RENDERPATH_SOFT:
6384 r_fb.usedepthtextures = true;
6388 if (r_viewscale_fpsscaling.integer)
6390 double actualframetime;
6391 double targetframetime;
6393 actualframetime = r_refdef.lastdrawscreentime;
6394 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6395 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6396 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6397 if (r_viewscale_fpsscaling_stepsize.value > 0)
6398 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6399 viewscalefpsadjusted += adjust;
6400 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6403 viewscalefpsadjusted = 1.0f;
6405 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6407 switch(vid.renderpath)
6409 case RENDERPATH_GL20:
6410 case RENDERPATH_D3D9:
6411 case RENDERPATH_D3D10:
6412 case RENDERPATH_D3D11:
6413 case RENDERPATH_SOFT:
6414 case RENDERPATH_GLES2:
6416 case RENDERPATH_GL11:
6417 case RENDERPATH_GL13:
6418 case RENDERPATH_GLES1:
6422 // set bloomwidth and bloomheight to the bloom resolution that will be
6423 // used (often less than the screen resolution for faster rendering)
6424 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6425 r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6426 r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6427 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6428 r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6430 // calculate desired texture sizes
6431 if (vid.support.arb_texture_non_power_of_two)
6433 screentexturewidth = vid.width;
6434 screentextureheight = vid.height;
6435 bloomtexturewidth = r_fb.bloomwidth;
6436 bloomtextureheight = r_fb.bloomheight;
6440 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
6441 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
6442 for (bloomtexturewidth = 1;bloomtexturewidth < r_fb.bloomwidth ;bloomtexturewidth *= 2);
6443 for (bloomtextureheight = 1;bloomtextureheight < r_fb.bloomheight;bloomtextureheight *= 2);
6446 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))
6448 Cvar_SetValueQuick(&r_bloom, 0);
6449 Cvar_SetValueQuick(&r_motionblur, 0);
6450 Cvar_SetValueQuick(&r_damageblur, 0);
6453 if (!((r_glsl_postprocess.integer || r_fxaa.integer) || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6455 && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6457 && r_viewscale.value == 1.0f
6458 && !r_viewscale_fpsscaling.integer)
6459 screentexturewidth = screentextureheight = 0;
6460 if (!r_bloom.integer)
6461 bloomtexturewidth = bloomtextureheight = 0;
6463 // allocate textures as needed
6464 if (r_fb.screentexturewidth != screentexturewidth
6465 || r_fb.screentextureheight != screentextureheight
6466 || r_fb.bloomtexturewidth != bloomtexturewidth
6467 || r_fb.bloomtextureheight != bloomtextureheight
6468 || r_fb.textype != textype
6469 || useviewfbo != (r_fb.fbo != 0))
6471 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6473 if (r_fb.bloomtexture[i])
6474 R_FreeTexture(r_fb.bloomtexture[i]);
6475 r_fb.bloomtexture[i] = NULL;
6477 if (r_fb.bloomfbo[i])
6478 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6479 r_fb.bloomfbo[i] = 0;
6483 R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6486 if (r_fb.colortexture)
6487 R_FreeTexture(r_fb.colortexture);
6488 r_fb.colortexture = NULL;
6490 if (r_fb.depthtexture)
6491 R_FreeTexture(r_fb.depthtexture);
6492 r_fb.depthtexture = NULL;
6494 if (r_fb.ghosttexture)
6495 R_FreeTexture(r_fb.ghosttexture);
6496 r_fb.ghosttexture = NULL;
6498 r_fb.screentexturewidth = screentexturewidth;
6499 r_fb.screentextureheight = screentextureheight;
6500 r_fb.bloomtexturewidth = bloomtexturewidth;
6501 r_fb.bloomtextureheight = bloomtextureheight;
6502 r_fb.textype = textype;
6504 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6506 if (r_motionblur.value > 0 || r_damageblur.value > 0)
6507 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);
6508 r_fb.ghosttexture_valid = false;
6509 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);
6512 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6513 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6514 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6518 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6520 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6522 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);
6524 r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6529 // bloom texture is a different resolution
6530 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6531 r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6532 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6533 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6534 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6536 // set up a texcoord array for the full resolution screen image
6537 // (we have to keep this around to copy back during final render)
6538 r_fb.screentexcoord2f[0] = 0;
6539 r_fb.screentexcoord2f[1] = (float)viewheight / (float)r_fb.screentextureheight;
6540 r_fb.screentexcoord2f[2] = (float)viewwidth / (float)r_fb.screentexturewidth;
6541 r_fb.screentexcoord2f[3] = (float)viewheight / (float)r_fb.screentextureheight;
6542 r_fb.screentexcoord2f[4] = (float)viewwidth / (float)r_fb.screentexturewidth;
6543 r_fb.screentexcoord2f[5] = 0;
6544 r_fb.screentexcoord2f[6] = 0;
6545 r_fb.screentexcoord2f[7] = 0;
6549 for (i = 1;i < 8;i += 2)
6551 r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6555 // set up a texcoord array for the reduced resolution bloom image
6556 // (which will be additive blended over the screen image)
6557 r_fb.bloomtexcoord2f[0] = 0;
6558 r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6559 r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6560 r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6561 r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6562 r_fb.bloomtexcoord2f[5] = 0;
6563 r_fb.bloomtexcoord2f[6] = 0;
6564 r_fb.bloomtexcoord2f[7] = 0;
6566 switch(vid.renderpath)
6568 case RENDERPATH_GL11:
6569 case RENDERPATH_GL13:
6570 case RENDERPATH_GL20:
6571 case RENDERPATH_SOFT:
6572 case RENDERPATH_GLES1:
6573 case RENDERPATH_GLES2:
6575 case RENDERPATH_D3D9:
6576 case RENDERPATH_D3D10:
6577 case RENDERPATH_D3D11:
6578 for (i = 0;i < 4;i++)
6580 r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6581 r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6582 r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6583 r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6588 R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6591 r_refdef.view.clear = true;
6594 static void R_Bloom_MakeTexture(void)
6597 float xoffset, yoffset, r, brighten;
6599 float colorscale = r_bloom_colorscale.value;
6601 r_refdef.stats[r_stat_bloom]++;
6604 // this copy is unnecessary since it happens in R_BlendView already
6607 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);
6608 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6612 // scale down screen texture to the bloom texture size
6614 r_fb.bloomindex = 0;
6615 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6616 R_SetViewport(&r_fb.bloomviewport);
6617 GL_DepthTest(false);
6618 GL_BlendFunc(GL_ONE, GL_ZERO);
6619 GL_Color(colorscale, colorscale, colorscale, 1);
6620 // 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...
6621 switch(vid.renderpath)
6623 case RENDERPATH_GL11:
6624 case RENDERPATH_GL13:
6625 case RENDERPATH_GL20:
6626 case RENDERPATH_GLES1:
6627 case RENDERPATH_GLES2:
6628 case RENDERPATH_SOFT:
6629 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6631 case RENDERPATH_D3D9:
6632 case RENDERPATH_D3D10:
6633 case RENDERPATH_D3D11:
6634 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6637 // TODO: do boxfilter scale-down in shader?
6638 R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6639 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6640 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6642 // we now have a properly scaled bloom image
6643 if (!r_fb.bloomfbo[r_fb.bloomindex])
6645 // copy it into the bloom texture
6646 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);
6647 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6650 // multiply bloom image by itself as many times as desired
6651 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6653 intex = r_fb.bloomtexture[r_fb.bloomindex];
6654 r_fb.bloomindex ^= 1;
6655 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6657 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6658 if (!r_fb.bloomfbo[r_fb.bloomindex])
6660 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6661 GL_Color(r,r,r,1); // apply fix factor
6666 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6667 GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6668 GL_Color(1,1,1,1); // no fix factor supported here
6670 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6671 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6672 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6673 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6675 if (!r_fb.bloomfbo[r_fb.bloomindex])
6677 // copy the darkened image to a texture
6678 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);
6679 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6683 range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6684 brighten = r_bloom_brighten.value;
6685 brighten = sqrt(brighten);
6687 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6689 for (dir = 0;dir < 2;dir++)
6691 intex = r_fb.bloomtexture[r_fb.bloomindex];
6692 r_fb.bloomindex ^= 1;
6693 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6694 // blend on at multiple vertical offsets to achieve a vertical blur
6695 // TODO: do offset blends using GLSL
6696 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6697 GL_BlendFunc(GL_ONE, GL_ZERO);
6698 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6699 for (x = -range;x <= range;x++)
6701 if (!dir){xoffset = 0;yoffset = x;}
6702 else {xoffset = x;yoffset = 0;}
6703 xoffset /= (float)r_fb.bloomtexturewidth;
6704 yoffset /= (float)r_fb.bloomtextureheight;
6705 // compute a texcoord array with the specified x and y offset
6706 r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6707 r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6708 r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6709 r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6710 r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6711 r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6712 r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6713 r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6714 // this r value looks like a 'dot' particle, fading sharply to
6715 // black at the edges
6716 // (probably not realistic but looks good enough)
6717 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6718 //r = brighten/(range*2+1);
6719 r = brighten / (range * 2 + 1);
6721 r *= (1 - x*x/(float)(range*range));
6722 GL_Color(r, r, r, 1);
6723 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6724 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6725 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6726 GL_BlendFunc(GL_ONE, GL_ONE);
6729 if (!r_fb.bloomfbo[r_fb.bloomindex])
6731 // copy the vertically or horizontally blurred bloom view to a texture
6732 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);
6733 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6738 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6740 unsigned int permutation;
6741 float uservecs[4][4];
6743 R_EntityMatrix(&identitymatrix);
6745 switch (vid.renderpath)
6747 case RENDERPATH_GL20:
6748 case RENDERPATH_D3D9:
6749 case RENDERPATH_D3D10:
6750 case RENDERPATH_D3D11:
6751 case RENDERPATH_SOFT:
6752 case RENDERPATH_GLES2:
6754 (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6755 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6756 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6757 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6758 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6760 if (r_fb.colortexture)
6764 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);
6765 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6768 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6770 // declare variables
6771 float blur_factor, blur_mouseaccel, blur_velocity;
6772 static float blur_average;
6773 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6775 // set a goal for the factoring
6776 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value)
6777 / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6778 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value)
6779 / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6780 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value)
6781 + (blur_mouseaccel * r_motionblur_mousefactor.value));
6783 // from the goal, pick an averaged value between goal and last value
6784 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6785 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6787 // enforce minimum amount of blur
6788 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6790 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6792 // calculate values into a standard alpha
6793 cl.motionbluralpha = 1 - exp(-
6795 (r_motionblur.value * blur_factor / 80)
6797 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6800 max(0.0001, cl.time - cl.oldtime) // fps independent
6803 // randomization for the blur value to combat persistent ghosting
6804 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6805 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6808 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6809 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6811 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6812 GL_Color(1, 1, 1, cl.motionbluralpha);
6813 switch(vid.renderpath)
6815 case RENDERPATH_GL11:
6816 case RENDERPATH_GL13:
6817 case RENDERPATH_GL20:
6818 case RENDERPATH_GLES1:
6819 case RENDERPATH_GLES2:
6820 case RENDERPATH_SOFT:
6821 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6823 case RENDERPATH_D3D9:
6824 case RENDERPATH_D3D10:
6825 case RENDERPATH_D3D11:
6826 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6829 R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6830 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6831 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6834 // updates old view angles for next pass
6835 VectorCopy(cl.viewangles, blur_oldangles);
6837 // copy view into the ghost texture
6838 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);
6839 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6840 r_fb.ghosttexture_valid = true;
6845 // no r_fb.colortexture means we're rendering to the real fb
6846 // we may still have to do view tint...
6847 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6849 // apply a color tint to the whole view
6850 R_ResetViewRendering2D(0, NULL, NULL);
6851 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6852 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6853 R_SetupShader_Generic_NoTexture(false, true);
6854 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6855 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6857 break; // no screen processing, no bloom, skip it
6860 if (r_fb.bloomtexture[0])
6862 // make the bloom texture
6863 R_Bloom_MakeTexture();
6866 #if _MSC_VER >= 1400
6867 #define sscanf sscanf_s
6869 memset(uservecs, 0, sizeof(uservecs));
6870 if (r_glsl_postprocess_uservec1_enable.integer)
6871 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6872 if (r_glsl_postprocess_uservec2_enable.integer)
6873 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6874 if (r_glsl_postprocess_uservec3_enable.integer)
6875 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6876 if (r_glsl_postprocess_uservec4_enable.integer)
6877 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6879 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6880 GL_Color(1, 1, 1, 1);
6881 GL_BlendFunc(GL_ONE, GL_ZERO);
6883 switch(vid.renderpath)
6885 case RENDERPATH_GL20:
6886 case RENDERPATH_GLES2:
6887 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6888 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6889 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_fb.colortexture);
6890 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_fb.bloomtexture[r_fb.bloomindex]);
6891 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6892 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]);
6893 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6894 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]);
6895 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]);
6896 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]);
6897 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]);
6898 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6899 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6900 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);
6902 case RENDERPATH_D3D9:
6904 // 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...
6905 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6906 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6907 R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture);
6908 R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]);
6909 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6910 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6911 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6912 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6913 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6914 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6915 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6916 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6917 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6918 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6921 case RENDERPATH_D3D10:
6922 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6924 case RENDERPATH_D3D11:
6925 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6927 case RENDERPATH_SOFT:
6928 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6929 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6930 R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture);
6931 R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]);
6932 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6933 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6934 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6935 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6936 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6937 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6938 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6939 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6940 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6941 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6946 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6947 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6949 case RENDERPATH_GL11:
6950 case RENDERPATH_GL13:
6951 case RENDERPATH_GLES1:
6952 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6954 // apply a color tint to the whole view
6955 R_ResetViewRendering2D(0, NULL, NULL);
6956 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6957 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6958 R_SetupShader_Generic_NoTexture(false, true);
6959 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6960 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6966 matrix4x4_t r_waterscrollmatrix;
6968 void R_UpdateFog(void)
6971 if (gamemode == GAME_NEHAHRA)
6973 if (gl_fogenable.integer)
6975 r_refdef.oldgl_fogenable = true;
6976 r_refdef.fog_density = gl_fogdensity.value;
6977 r_refdef.fog_red = gl_fogred.value;
6978 r_refdef.fog_green = gl_foggreen.value;
6979 r_refdef.fog_blue = gl_fogblue.value;
6980 r_refdef.fog_alpha = 1;
6981 r_refdef.fog_start = 0;
6982 r_refdef.fog_end = gl_skyclip.value;
6983 r_refdef.fog_height = 1<<30;
6984 r_refdef.fog_fadedepth = 128;
6986 else if (r_refdef.oldgl_fogenable)
6988 r_refdef.oldgl_fogenable = false;
6989 r_refdef.fog_density = 0;
6990 r_refdef.fog_red = 0;
6991 r_refdef.fog_green = 0;
6992 r_refdef.fog_blue = 0;
6993 r_refdef.fog_alpha = 0;
6994 r_refdef.fog_start = 0;
6995 r_refdef.fog_end = 0;
6996 r_refdef.fog_height = 1<<30;
6997 r_refdef.fog_fadedepth = 128;
7002 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
7003 r_refdef.fog_start = max(0, r_refdef.fog_start);
7004 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
7006 if (r_refdef.fog_density && r_drawfog.integer)
7008 r_refdef.fogenabled = true;
7009 // this is the point where the fog reaches 0.9986 alpha, which we
7010 // consider a good enough cutoff point for the texture
7011 // (0.9986 * 256 == 255.6)
7012 if (r_fog_exp2.integer)
7013 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
7015 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
7016 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
7017 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
7018 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
7019 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
7020 R_BuildFogHeightTexture();
7021 // fog color was already set
7022 // update the fog texture
7023 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)
7024 R_BuildFogTexture();
7025 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
7026 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
7029 r_refdef.fogenabled = false;
7032 if (r_refdef.fog_density)
7034 r_refdef.fogcolor[0] = r_refdef.fog_red;
7035 r_refdef.fogcolor[1] = r_refdef.fog_green;
7036 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7038 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7039 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7040 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7041 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7045 VectorCopy(r_refdef.fogcolor, fogvec);
7046 // color.rgb *= ContrastBoost * SceneBrightness;
7047 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7048 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7049 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7050 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7055 void R_UpdateVariables(void)
7059 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7061 r_refdef.farclip = r_farclip_base.value;
7062 if (r_refdef.scene.worldmodel)
7063 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7064 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7066 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7067 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7068 r_refdef.polygonfactor = 0;
7069 r_refdef.polygonoffset = 0;
7070 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7071 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7073 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7074 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7075 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
7076 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7077 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7078 if (FAKELIGHT_ENABLED)
7080 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
7082 else if (r_refdef.scene.worldmodel)
7084 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
7086 if (r_showsurfaces.integer)
7088 r_refdef.scene.rtworld = false;
7089 r_refdef.scene.rtworldshadows = false;
7090 r_refdef.scene.rtdlight = false;
7091 r_refdef.scene.rtdlightshadows = false;
7092 r_refdef.lightmapintensity = 0;
7095 r_gpuskeletal = false;
7096 switch(vid.renderpath)
7098 case RENDERPATH_GL20:
7099 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
7100 case RENDERPATH_D3D9:
7101 case RENDERPATH_D3D10:
7102 case RENDERPATH_D3D11:
7103 case RENDERPATH_SOFT:
7104 case RENDERPATH_GLES2:
7105 if(v_glslgamma.integer && !vid_gammatables_trivial)
7107 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7109 // build GLSL gamma texture
7110 #define RAMPWIDTH 256
7111 unsigned short ramp[RAMPWIDTH * 3];
7112 unsigned char rampbgr[RAMPWIDTH][4];
7115 r_texture_gammaramps_serial = vid_gammatables_serial;
7117 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7118 for(i = 0; i < RAMPWIDTH; ++i)
7120 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7121 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7122 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7125 if (r_texture_gammaramps)
7127 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7131 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7137 // remove GLSL gamma texture
7140 case RENDERPATH_GL11:
7141 case RENDERPATH_GL13:
7142 case RENDERPATH_GLES1:
7147 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7148 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7154 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7155 if( scenetype != r_currentscenetype ) {
7156 // store the old scenetype
7157 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7158 r_currentscenetype = scenetype;
7159 // move in the new scene
7160 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7169 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7171 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7172 if( scenetype == r_currentscenetype ) {
7173 return &r_refdef.scene;
7175 return &r_scenes_store[ scenetype ];
7179 static int R_SortEntities_Compare(const void *ap, const void *bp)
7181 const entity_render_t *a = *(const entity_render_t **)ap;
7182 const entity_render_t *b = *(const entity_render_t **)bp;
7185 if(a->model < b->model)
7187 if(a->model > b->model)
7191 // TODO possibly calculate the REAL skinnum here first using
7193 if(a->skinnum < b->skinnum)
7195 if(a->skinnum > b->skinnum)
7198 // everything we compared is equal
7201 static void R_SortEntities(void)
7203 // below or equal 2 ents, sorting never gains anything
7204 if(r_refdef.scene.numentities <= 2)
7207 qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7215 int dpsoftrast_test;
7216 extern cvar_t r_shadow_bouncegrid;
7217 void R_RenderView(void)
7219 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7221 rtexture_t *depthtexture;
7222 rtexture_t *colortexture;
7224 dpsoftrast_test = r_test.integer;
7226 if (r_timereport_active)
7227 R_TimeReport("start");
7228 r_textureframe++; // used only by R_GetCurrentTexture
7229 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7231 if(R_CompileShader_CheckStaticParms())
7234 if (!r_drawentities.integer)
7235 r_refdef.scene.numentities = 0;
7236 else if (r_sortentities.integer)
7239 R_AnimCache_ClearCache();
7241 /* adjust for stereo display */
7242 if(R_Stereo_Active())
7244 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);
7245 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7248 if (r_refdef.view.isoverlay)
7250 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7251 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7252 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7253 R_TimeReport("depthclear");
7255 r_refdef.view.showdebug = false;
7257 r_fb.water.enabled = false;
7258 r_fb.water.numwaterplanes = 0;
7260 R_RenderScene(0, NULL, NULL);
7262 r_refdef.view.matrix = originalmatrix;
7268 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7270 r_refdef.view.matrix = originalmatrix;
7274 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7276 if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7277 // in sRGB fallback, behave similar to true sRGB: convert this
7278 // value from linear to sRGB
7279 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7281 R_RenderView_UpdateViewVectors();
7283 R_Shadow_UpdateWorldLightSelection();
7285 R_Bloom_StartFrame();
7287 // apply bloom brightness offset
7288 if(r_fb.bloomtexture[0])
7289 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7291 R_Water_StartFrame();
7293 // now we probably have an fbo to render into
7295 depthtexture = r_fb.depthtexture;
7296 colortexture = r_fb.colortexture;
7299 if (r_timereport_active)
7300 R_TimeReport("viewsetup");
7302 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7304 if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7306 R_ClearScreen(r_refdef.fogenabled);
7307 if (r_timereport_active)
7308 R_TimeReport("viewclear");
7310 r_refdef.view.clear = true;
7312 r_refdef.view.showdebug = true;
7315 if (r_timereport_active)
7316 R_TimeReport("visibility");
7318 R_AnimCache_CacheVisibleEntities();
7319 if (r_timereport_active)
7320 R_TimeReport("animcache");
7322 R_Shadow_UpdateBounceGridTexture();
7323 if (r_timereport_active && r_shadow_bouncegrid.integer)
7324 R_TimeReport("bouncegrid");
7326 r_fb.water.numwaterplanes = 0;
7327 if (r_fb.water.enabled)
7328 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7330 R_RenderScene(fbo, depthtexture, colortexture);
7331 r_fb.water.numwaterplanes = 0;
7333 R_BlendView(fbo, depthtexture, colortexture);
7334 if (r_timereport_active)
7335 R_TimeReport("blendview");
7337 GL_Scissor(0, 0, vid.width, vid.height);
7338 GL_ScissorTest(false);
7340 r_refdef.view.matrix = originalmatrix;
7345 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7347 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7349 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7350 if (r_timereport_active)
7351 R_TimeReport("waterworld");
7354 // don't let sound skip if going slow
7355 if (r_refdef.scene.extraupdate)
7358 R_DrawModelsAddWaterPlanes();
7359 if (r_timereport_active)
7360 R_TimeReport("watermodels");
7362 if (r_fb.water.numwaterplanes)
7364 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7365 if (r_timereport_active)
7366 R_TimeReport("waterscenes");
7370 extern cvar_t cl_locs_show;
7371 static void R_DrawLocs(void);
7372 static void R_DrawEntityBBoxes(void);
7373 static void R_DrawModelDecals(void);
7374 extern cvar_t cl_decals_newsystem;
7375 extern qboolean r_shadow_usingdeferredprepass;
7376 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7378 qboolean shadowmapping = false;
7380 if (r_timereport_active)
7381 R_TimeReport("beginscene");
7383 r_refdef.stats[r_stat_renders]++;
7387 // don't let sound skip if going slow
7388 if (r_refdef.scene.extraupdate)
7391 R_MeshQueue_BeginScene();
7395 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);
7397 if (r_timereport_active)
7398 R_TimeReport("skystartframe");
7400 if (cl.csqc_vidvars.drawworld)
7402 // don't let sound skip if going slow
7403 if (r_refdef.scene.extraupdate)
7406 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7408 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7409 if (r_timereport_active)
7410 R_TimeReport("worldsky");
7413 if (R_DrawBrushModelsSky() && r_timereport_active)
7414 R_TimeReport("bmodelsky");
7416 if (skyrendermasked && skyrenderlater)
7418 // we have to force off the water clipping plane while rendering sky
7419 R_SetupView(false, fbo, depthtexture, colortexture);
7421 R_SetupView(true, fbo, depthtexture, colortexture);
7422 if (r_timereport_active)
7423 R_TimeReport("sky");
7427 R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7428 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7429 R_Shadow_PrepareModelShadows();
7430 if (r_timereport_active)
7431 R_TimeReport("preparelights");
7433 if (R_Shadow_ShadowMappingEnabled())
7434 shadowmapping = true;
7436 if (r_shadow_usingdeferredprepass)
7437 R_Shadow_DrawPrepass();
7439 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7441 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7442 if (r_timereport_active)
7443 R_TimeReport("worlddepth");
7445 if (r_depthfirst.integer >= 2)
7447 R_DrawModelsDepth();
7448 if (r_timereport_active)
7449 R_TimeReport("modeldepth");
7452 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7454 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7455 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7456 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7457 // don't let sound skip if going slow
7458 if (r_refdef.scene.extraupdate)
7462 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7464 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7465 if (r_timereport_active)
7466 R_TimeReport("world");
7469 // don't let sound skip if going slow
7470 if (r_refdef.scene.extraupdate)
7474 if (r_timereport_active)
7475 R_TimeReport("models");
7477 // don't let sound skip if going slow
7478 if (r_refdef.scene.extraupdate)
7481 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7483 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7484 R_DrawModelShadows(fbo, depthtexture, colortexture);
7485 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7486 // don't let sound skip if going slow
7487 if (r_refdef.scene.extraupdate)
7491 if (!r_shadow_usingdeferredprepass)
7493 R_Shadow_DrawLights();
7494 if (r_timereport_active)
7495 R_TimeReport("rtlights");
7498 // don't let sound skip if going slow
7499 if (r_refdef.scene.extraupdate)
7502 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7504 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7505 R_DrawModelShadows(fbo, depthtexture, colortexture);
7506 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7507 // don't let sound skip if going slow
7508 if (r_refdef.scene.extraupdate)
7512 if (cl.csqc_vidvars.drawworld)
7514 if (cl_decals_newsystem.integer)
7516 R_DrawModelDecals();
7517 if (r_timereport_active)
7518 R_TimeReport("modeldecals");
7523 if (r_timereport_active)
7524 R_TimeReport("decals");
7528 if (r_timereport_active)
7529 R_TimeReport("particles");
7532 if (r_timereport_active)
7533 R_TimeReport("explosions");
7535 R_DrawLightningBeams();
7536 if (r_timereport_active)
7537 R_TimeReport("lightning");
7541 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7543 if (r_refdef.view.showdebug)
7545 if (cl_locs_show.integer)
7548 if (r_timereport_active)
7549 R_TimeReport("showlocs");
7552 if (r_drawportals.integer)
7555 if (r_timereport_active)
7556 R_TimeReport("portals");
7559 if (r_showbboxes.value > 0)
7561 R_DrawEntityBBoxes();
7562 if (r_timereport_active)
7563 R_TimeReport("bboxes");
7567 if (r_transparent.integer)
7569 R_MeshQueue_RenderTransparent();
7570 if (r_timereport_active)
7571 R_TimeReport("drawtrans");
7574 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))
7576 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7577 if (r_timereport_active)
7578 R_TimeReport("worlddebug");
7579 R_DrawModelsDebug();
7580 if (r_timereport_active)
7581 R_TimeReport("modeldebug");
7584 if (cl.csqc_vidvars.drawworld)
7586 R_Shadow_DrawCoronas();
7587 if (r_timereport_active)
7588 R_TimeReport("coronas");
7593 GL_DepthTest(false);
7594 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7595 GL_Color(1, 1, 1, 1);
7596 qglBegin(GL_POLYGON);
7597 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7598 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7599 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7600 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7602 qglBegin(GL_POLYGON);
7603 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]);
7604 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]);
7605 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]);
7606 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]);
7608 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7612 // don't let sound skip if going slow
7613 if (r_refdef.scene.extraupdate)
7617 static const unsigned short bboxelements[36] =
7627 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7630 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7632 RSurf_ActiveWorldEntity();
7634 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7635 GL_DepthMask(false);
7636 GL_DepthRange(0, 1);
7637 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7638 // R_Mesh_ResetTextureState();
7640 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7641 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7642 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7643 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7644 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7645 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7646 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7647 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7648 R_FillColors(color4f, 8, cr, cg, cb, ca);
7649 if (r_refdef.fogenabled)
7651 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7653 f1 = RSurf_FogVertex(v);
7655 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7656 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7657 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7660 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7661 R_Mesh_ResetTextureState();
7662 R_SetupShader_Generic_NoTexture(false, false);
7663 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7666 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7668 prvm_prog_t *prog = SVVM_prog;
7671 prvm_edict_t *edict;
7673 // this function draws bounding boxes of server entities
7677 GL_CullFace(GL_NONE);
7678 R_SetupShader_Generic_NoTexture(false, false);
7680 for (i = 0;i < numsurfaces;i++)
7682 edict = PRVM_EDICT_NUM(surfacelist[i]);
7683 switch ((int)PRVM_serveredictfloat(edict, solid))
7685 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7686 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7687 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7688 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7689 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7690 case SOLID_CORPSE: Vector4Set(color, 1, 0.5, 0, 0.05);break;
7691 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7693 color[3] *= r_showbboxes.value;
7694 color[3] = bound(0, color[3], 1);
7695 GL_DepthTest(!r_showdisabledepthtest.integer);
7696 GL_CullFace(r_refdef.view.cullface_front);
7697 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7701 static void R_DrawEntityBBoxes(void)
7704 prvm_edict_t *edict;
7706 prvm_prog_t *prog = SVVM_prog;
7708 // this function draws bounding boxes of server entities
7712 for (i = 0;i < prog->num_edicts;i++)
7714 edict = PRVM_EDICT_NUM(i);
7715 if (edict->priv.server->free)
7717 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7718 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7720 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7722 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7723 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7727 static const int nomodelelement3i[24] =
7739 static const unsigned short nomodelelement3s[24] =
7751 static const float nomodelvertex3f[6*3] =
7761 static const float nomodelcolor4f[6*4] =
7763 0.0f, 0.0f, 0.5f, 1.0f,
7764 0.0f, 0.0f, 0.5f, 1.0f,
7765 0.0f, 0.5f, 0.0f, 1.0f,
7766 0.0f, 0.5f, 0.0f, 1.0f,
7767 0.5f, 0.0f, 0.0f, 1.0f,
7768 0.5f, 0.0f, 0.0f, 1.0f
7771 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7777 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);
7779 // this is only called once per entity so numsurfaces is always 1, and
7780 // surfacelist is always {0}, so this code does not handle batches
7782 if (rsurface.ent_flags & RENDER_ADDITIVE)
7784 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7785 GL_DepthMask(false);
7787 else if (rsurface.colormod[3] < 1)
7789 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7790 GL_DepthMask(false);
7794 GL_BlendFunc(GL_ONE, GL_ZERO);
7797 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7798 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7799 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7800 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7801 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7802 for (i = 0, c = color4f;i < 6;i++, c += 4)
7804 c[0] *= rsurface.colormod[0];
7805 c[1] *= rsurface.colormod[1];
7806 c[2] *= rsurface.colormod[2];
7807 c[3] *= rsurface.colormod[3];
7809 if (r_refdef.fogenabled)
7811 for (i = 0, c = color4f;i < 6;i++, c += 4)
7813 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7815 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7816 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7817 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7820 // R_Mesh_ResetTextureState();
7821 R_SetupShader_Generic_NoTexture(false, false);
7822 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7823 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7826 void R_DrawNoModel(entity_render_t *ent)
7829 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7830 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7831 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7833 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7836 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7838 vec3_t right1, right2, diff, normal;
7840 VectorSubtract (org2, org1, normal);
7842 // calculate 'right' vector for start
7843 VectorSubtract (r_refdef.view.origin, org1, diff);
7844 CrossProduct (normal, diff, right1);
7845 VectorNormalize (right1);
7847 // calculate 'right' vector for end
7848 VectorSubtract (r_refdef.view.origin, org2, diff);
7849 CrossProduct (normal, diff, right2);
7850 VectorNormalize (right2);
7852 vert[ 0] = org1[0] + width * right1[0];
7853 vert[ 1] = org1[1] + width * right1[1];
7854 vert[ 2] = org1[2] + width * right1[2];
7855 vert[ 3] = org1[0] - width * right1[0];
7856 vert[ 4] = org1[1] - width * right1[1];
7857 vert[ 5] = org1[2] - width * right1[2];
7858 vert[ 6] = org2[0] - width * right2[0];
7859 vert[ 7] = org2[1] - width * right2[1];
7860 vert[ 8] = org2[2] - width * right2[2];
7861 vert[ 9] = org2[0] + width * right2[0];
7862 vert[10] = org2[1] + width * right2[1];
7863 vert[11] = org2[2] + width * right2[2];
7866 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)
7868 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7869 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7870 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7871 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7872 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7873 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7874 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7875 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7876 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7877 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7878 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7879 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7882 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7887 VectorSet(v, x, y, z);
7888 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7889 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7891 if (i == mesh->numvertices)
7893 if (mesh->numvertices < mesh->maxvertices)
7895 VectorCopy(v, vertex3f);
7896 mesh->numvertices++;
7898 return mesh->numvertices;
7904 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7908 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7909 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7910 e = mesh->element3i + mesh->numtriangles * 3;
7911 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7913 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7914 if (mesh->numtriangles < mesh->maxtriangles)
7919 mesh->numtriangles++;
7921 element[1] = element[2];
7925 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7929 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7930 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7931 e = mesh->element3i + mesh->numtriangles * 3;
7932 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7934 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7935 if (mesh->numtriangles < mesh->maxtriangles)
7940 mesh->numtriangles++;
7942 element[1] = element[2];
7946 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7947 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7949 int planenum, planenum2;
7952 mplane_t *plane, *plane2;
7954 double temppoints[2][256*3];
7955 // figure out how large a bounding box we need to properly compute this brush
7957 for (w = 0;w < numplanes;w++)
7958 maxdist = max(maxdist, fabs(planes[w].dist));
7959 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7960 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7961 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7965 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7966 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7968 if (planenum2 == planenum)
7970 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);
7973 if (tempnumpoints < 3)
7975 // generate elements forming a triangle fan for this polygon
7976 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7980 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)
7982 texturelayer_t *layer;
7983 layer = t->currentlayers + t->currentnumlayers++;
7985 layer->depthmask = depthmask;
7986 layer->blendfunc1 = blendfunc1;
7987 layer->blendfunc2 = blendfunc2;
7988 layer->texture = texture;
7989 layer->texmatrix = *matrix;
7990 layer->color[0] = r;
7991 layer->color[1] = g;
7992 layer->color[2] = b;
7993 layer->color[3] = a;
7996 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7998 if(parms[0] == 0 && parms[1] == 0)
8000 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8001 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
8006 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8009 index = parms[2] + rsurface.shadertime * parms[3];
8010 index -= floor(index);
8011 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
8014 case Q3WAVEFUNC_NONE:
8015 case Q3WAVEFUNC_NOISE:
8016 case Q3WAVEFUNC_COUNT:
8019 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8020 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8021 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8022 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8023 case Q3WAVEFUNC_TRIANGLE:
8025 f = index - floor(index);
8038 f = parms[0] + parms[1] * f;
8039 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8040 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
8044 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8051 matrix4x4_t matrix, temp;
8052 // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
8053 // it's better to have one huge fixup every 9 hours than gradual
8054 // degradation over time which looks consistently bad after many hours.
8056 // tcmod scroll in particular suffers from this degradation which can't be
8057 // effectively worked around even with floor() tricks because we don't
8058 // know if tcmod scroll is the last tcmod being applied, and for clampmap
8059 // a workaround involving floor() would be incorrect anyway...
8060 shadertime = rsurface.shadertime;
8061 if (shadertime >= 32768.0f)
8062 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
8063 switch(tcmod->tcmod)
8067 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8068 matrix = r_waterscrollmatrix;
8070 matrix = identitymatrix;
8072 case Q3TCMOD_ENTITYTRANSLATE:
8073 // this is used in Q3 to allow the gamecode to control texcoord
8074 // scrolling on the entity, which is not supported in darkplaces yet.
8075 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8077 case Q3TCMOD_ROTATE:
8078 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8079 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
8080 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8083 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8085 case Q3TCMOD_SCROLL:
8086 // this particular tcmod is a "bug for bug" compatible one with regards to
8087 // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
8088 // specifically did the wrapping and so we must mimic that...
8089 offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
8090 offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
8091 Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
8093 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8094 w = (int) tcmod->parms[0];
8095 h = (int) tcmod->parms[1];
8096 f = rsurface.shadertime / (tcmod->parms[2] * w * h);
8098 idx = (int) floor(f * w * h);
8099 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8101 case Q3TCMOD_STRETCH:
8102 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8103 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8105 case Q3TCMOD_TRANSFORM:
8106 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
8107 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
8108 VectorSet(tcmat + 6, 0 , 0 , 1);
8109 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
8110 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8112 case Q3TCMOD_TURBULENT:
8113 // this is handled in the RSurf_PrepareVertices function
8114 matrix = identitymatrix;
8118 Matrix4x4_Concat(texmatrix, &matrix, &temp);
8121 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8123 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8124 char name[MAX_QPATH];
8125 skinframe_t *skinframe;
8126 unsigned char pixels[296*194];
8127 strlcpy(cache->name, skinname, sizeof(cache->name));
8128 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8129 if (developer_loading.integer)
8130 Con_Printf("loading %s\n", name);
8131 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8132 if (!skinframe || !skinframe->base)
8135 fs_offset_t filesize;
8137 f = FS_LoadFile(name, tempmempool, true, &filesize);
8140 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8141 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8145 cache->skinframe = skinframe;
8148 texture_t *R_GetCurrentTexture(texture_t *t)
8151 const entity_render_t *ent = rsurface.entity;
8152 dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8153 q3shaderinfo_layer_tcmod_t *tcmod;
8155 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8156 return t->currentframe;
8157 t->update_lastrenderframe = r_textureframe;
8158 t->update_lastrenderentity = (void *)ent;
8160 if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8161 t->camera_entity = ent->entitynumber;
8163 t->camera_entity = 0;
8165 // switch to an alternate material if this is a q1bsp animated material
8167 texture_t *texture = t;
8168 int s = rsurface.ent_skinnum;
8169 if ((unsigned int)s >= (unsigned int)model->numskins)
8171 if (model->skinscenes)
8173 if (model->skinscenes[s].framecount > 1)
8174 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8176 s = model->skinscenes[s].firstframe;
8179 t = t + s * model->num_surfaces;
8182 // use an alternate animation if the entity's frame is not 0,
8183 // and only if the texture has an alternate animation
8184 if (t->animated == 2) // q2bsp
8185 t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]];
8186 else if (rsurface.ent_alttextures && t->anim_total[1])
8187 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8189 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8191 texture->currentframe = t;
8194 // update currentskinframe to be a qw skin or animation frame
8195 if (rsurface.ent_qwskin >= 0)
8197 i = rsurface.ent_qwskin;
8198 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8200 r_qwskincache_size = cl.maxclients;
8202 Mem_Free(r_qwskincache);
8203 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8205 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8206 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8207 t->currentskinframe = r_qwskincache[i].skinframe;
8208 if (t->currentskinframe == NULL)
8209 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8211 else if (t->numskinframes >= 2)
8212 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8213 if (t->backgroundnumskinframes >= 2)
8214 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
8216 t->currentmaterialflags = t->basematerialflags;
8217 t->currentalpha = rsurface.colormod[3] * t->basealpha;
8218 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8219 t->currentalpha *= r_wateralpha.value;
8220 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8221 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8222 if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8223 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8224 if (!(rsurface.ent_flags & RENDER_LIGHT))
8225 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8226 else if (FAKELIGHT_ENABLED)
8228 // no modellight if using fakelight for the map
8230 else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8232 // pick a model lighting mode
8233 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8234 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8236 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8238 if (rsurface.ent_flags & RENDER_ADDITIVE)
8239 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8240 else if (t->currentalpha < 1)
8241 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8242 // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8243 if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8244 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8245 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8246 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8247 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8248 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8249 if (t->backgroundnumskinframes)
8250 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8251 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8253 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8254 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8257 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8258 if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8260 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8261 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8263 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8264 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8266 // there is no tcmod
8267 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8269 t->currenttexmatrix = r_waterscrollmatrix;
8270 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8272 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8274 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8275 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8278 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8279 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8280 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8281 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8283 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8284 if (t->currentskinframe->qpixels)
8285 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8286 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8287 if (!t->basetexture)
8288 t->basetexture = r_texture_notexture;
8289 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8290 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8291 t->nmaptexture = t->currentskinframe->nmap;
8292 if (!t->nmaptexture)
8293 t->nmaptexture = r_texture_blanknormalmap;
8294 t->glosstexture = r_texture_black;
8295 t->glowtexture = t->currentskinframe->glow;
8296 t->fogtexture = t->currentskinframe->fog;
8297 t->reflectmasktexture = t->currentskinframe->reflect;
8298 if (t->backgroundnumskinframes)
8300 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8301 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8302 t->backgroundglosstexture = r_texture_black;
8303 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8304 if (!t->backgroundnmaptexture)
8305 t->backgroundnmaptexture = r_texture_blanknormalmap;
8306 // make sure that if glow is going to be used, both textures are not NULL
8307 if (!t->backgroundglowtexture && t->glowtexture)
8308 t->backgroundglowtexture = r_texture_black;
8309 if (!t->glowtexture && t->backgroundglowtexture)
8310 t->glowtexture = r_texture_black;
8314 t->backgroundbasetexture = r_texture_white;
8315 t->backgroundnmaptexture = r_texture_blanknormalmap;
8316 t->backgroundglosstexture = r_texture_black;
8317 t->backgroundglowtexture = NULL;
8319 t->specularpower = r_shadow_glossexponent.value;
8320 // TODO: store reference values for these in the texture?
8321 t->specularscale = 0;
8322 if (r_shadow_gloss.integer > 0)
8324 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8326 if (r_shadow_glossintensity.value > 0)
8328 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8329 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8330 t->specularscale = r_shadow_glossintensity.value;
8333 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8335 t->glosstexture = r_texture_white;
8336 t->backgroundglosstexture = r_texture_white;
8337 t->specularscale = r_shadow_gloss2intensity.value;
8338 t->specularpower = r_shadow_gloss2exponent.value;
8341 t->specularscale *= t->specularscalemod;
8342 t->specularpower *= t->specularpowermod;
8343 t->rtlightambient = 0;
8345 // lightmaps mode looks bad with dlights using actual texturing, so turn
8346 // off the colormap and glossmap, but leave the normalmap on as it still
8347 // accurately represents the shading involved
8348 if (gl_lightmaps.integer)
8350 t->basetexture = r_texture_grey128;
8351 t->pantstexture = r_texture_black;
8352 t->shirttexture = r_texture_black;
8353 if (gl_lightmaps.integer < 2)
8354 t->nmaptexture = r_texture_blanknormalmap;
8355 t->glosstexture = r_texture_black;
8356 t->glowtexture = NULL;
8357 t->fogtexture = NULL;
8358 t->reflectmasktexture = NULL;
8359 t->backgroundbasetexture = NULL;
8360 if (gl_lightmaps.integer < 2)
8361 t->backgroundnmaptexture = r_texture_blanknormalmap;
8362 t->backgroundglosstexture = r_texture_black;
8363 t->backgroundglowtexture = NULL;
8364 t->specularscale = 0;
8365 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8368 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8369 VectorClear(t->dlightcolor);
8370 t->currentnumlayers = 0;
8371 if (t->currentmaterialflags & MATERIALFLAG_WALL)
8373 int blendfunc1, blendfunc2;
8375 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8377 blendfunc1 = GL_SRC_ALPHA;
8378 blendfunc2 = GL_ONE;
8380 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8382 blendfunc1 = GL_SRC_ALPHA;
8383 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8385 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8387 blendfunc1 = t->customblendfunc[0];
8388 blendfunc2 = t->customblendfunc[1];
8392 blendfunc1 = GL_ONE;
8393 blendfunc2 = GL_ZERO;
8395 // don't colormod evilblend textures
8396 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8397 VectorSet(t->lightmapcolor, 1, 1, 1);
8398 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8399 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8401 // fullbright is not affected by r_refdef.lightmapintensity
8402 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]);
8403 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8404 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]);
8405 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8406 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]);
8410 vec3_t ambientcolor;
8412 // set the color tint used for lights affecting this surface
8413 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8415 // q3bsp has no lightmap updates, so the lightstylevalue that
8416 // would normally be baked into the lightmap must be
8417 // applied to the color
8418 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8419 if (model->type == mod_brushq3)
8420 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8421 colorscale *= r_refdef.lightmapintensity;
8422 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8423 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8424 // basic lit geometry
8425 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]);
8426 // add pants/shirt if needed
8427 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8428 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]);
8429 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8430 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]);
8431 // now add ambient passes if needed
8432 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8434 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]);
8435 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8436 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]);
8437 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8438 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]);
8441 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8442 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]);
8443 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8445 // if this is opaque use alpha blend which will darken the earlier
8448 // if this is an alpha blended material, all the earlier passes
8449 // were darkened by fog already, so we only need to add the fog
8450 // color ontop through the fog mask texture
8452 // if this is an additive blended material, all the earlier passes
8453 // were darkened by fog already, and we should not add fog color
8454 // (because the background was not darkened, there is no fog color
8455 // that was lost behind it).
8456 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]);
8463 rsurfacestate_t rsurface;
8465 void RSurf_ActiveWorldEntity(void)
8467 dp_model_t *model = r_refdef.scene.worldmodel;
8468 //if (rsurface.entity == r_refdef.scene.worldentity)
8470 rsurface.entity = r_refdef.scene.worldentity;
8471 rsurface.skeleton = NULL;
8472 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8473 rsurface.ent_skinnum = 0;
8474 rsurface.ent_qwskin = -1;
8475 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8476 rsurface.shadertime = r_refdef.scene.time;
8477 rsurface.matrix = identitymatrix;
8478 rsurface.inversematrix = identitymatrix;
8479 rsurface.matrixscale = 1;
8480 rsurface.inversematrixscale = 1;
8481 R_EntityMatrix(&identitymatrix);
8482 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8483 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8484 rsurface.fograngerecip = r_refdef.fograngerecip;
8485 rsurface.fogheightfade = r_refdef.fogheightfade;
8486 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8487 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8488 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8489 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8490 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8491 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8492 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8493 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8494 rsurface.colormod[3] = 1;
8495 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);
8496 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8497 rsurface.frameblend[0].lerp = 1;
8498 rsurface.ent_alttextures = false;
8499 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8500 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8501 rsurface.entityskeletaltransform3x4 = NULL;
8502 rsurface.entityskeletaltransform3x4buffer = NULL;
8503 rsurface.entityskeletaltransform3x4offset = 0;
8504 rsurface.entityskeletaltransform3x4size = 0;;
8505 rsurface.entityskeletalnumtransforms = 0;
8506 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8507 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8508 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8509 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8510 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8511 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8512 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8513 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8514 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8515 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8516 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8517 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8518 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8519 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8520 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8521 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8522 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8523 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8524 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8525 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8526 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8527 rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8528 rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8529 rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8530 rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8531 rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8532 rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8533 rsurface.modelelement3i = model->surfmesh.data_element3i;
8534 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8535 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8536 rsurface.modelelement3s = model->surfmesh.data_element3s;
8537 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8538 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8539 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8540 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8541 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8542 rsurface.modelsurfaces = model->data_surfaces;
8543 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8544 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8545 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8546 rsurface.modelgeneratedvertex = false;
8547 rsurface.batchgeneratedvertex = false;
8548 rsurface.batchfirstvertex = 0;
8549 rsurface.batchnumvertices = 0;
8550 rsurface.batchfirsttriangle = 0;
8551 rsurface.batchnumtriangles = 0;
8552 rsurface.batchvertex3f = NULL;
8553 rsurface.batchvertex3f_vertexbuffer = NULL;
8554 rsurface.batchvertex3f_bufferoffset = 0;
8555 rsurface.batchsvector3f = NULL;
8556 rsurface.batchsvector3f_vertexbuffer = NULL;
8557 rsurface.batchsvector3f_bufferoffset = 0;
8558 rsurface.batchtvector3f = NULL;
8559 rsurface.batchtvector3f_vertexbuffer = NULL;
8560 rsurface.batchtvector3f_bufferoffset = 0;
8561 rsurface.batchnormal3f = NULL;
8562 rsurface.batchnormal3f_vertexbuffer = NULL;
8563 rsurface.batchnormal3f_bufferoffset = 0;
8564 rsurface.batchlightmapcolor4f = NULL;
8565 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8566 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8567 rsurface.batchtexcoordtexture2f = NULL;
8568 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8569 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8570 rsurface.batchtexcoordlightmap2f = NULL;
8571 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8572 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8573 rsurface.batchskeletalindex4ub = NULL;
8574 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8575 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8576 rsurface.batchskeletalweight4ub = NULL;
8577 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8578 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8579 rsurface.batchvertexmesh = NULL;
8580 rsurface.batchvertexmesh_vertexbuffer = NULL;
8581 rsurface.batchvertexmesh_bufferoffset = 0;
8582 rsurface.batchelement3i = NULL;
8583 rsurface.batchelement3i_indexbuffer = NULL;
8584 rsurface.batchelement3i_bufferoffset = 0;
8585 rsurface.batchelement3s = NULL;
8586 rsurface.batchelement3s_indexbuffer = NULL;
8587 rsurface.batchelement3s_bufferoffset = 0;
8588 rsurface.passcolor4f = NULL;
8589 rsurface.passcolor4f_vertexbuffer = NULL;
8590 rsurface.passcolor4f_bufferoffset = 0;
8591 rsurface.forcecurrenttextureupdate = false;
8594 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8596 dp_model_t *model = ent->model;
8597 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8599 rsurface.entity = (entity_render_t *)ent;
8600 rsurface.skeleton = ent->skeleton;
8601 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8602 rsurface.ent_skinnum = ent->skinnum;
8603 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;
8604 rsurface.ent_flags = ent->flags;
8605 rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8606 rsurface.matrix = ent->matrix;
8607 rsurface.inversematrix = ent->inversematrix;
8608 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8609 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8610 R_EntityMatrix(&rsurface.matrix);
8611 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8612 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8613 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8614 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8615 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8616 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8617 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8618 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8619 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8620 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8621 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8622 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8623 rsurface.colormod[3] = ent->alpha;
8624 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8625 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8626 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8627 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8628 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8629 if (ent->model->brush.submodel && !prepass)
8631 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8632 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8634 // if the animcache code decided it should use the shader path, skip the deform step
8635 rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8636 rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8637 rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8638 rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8639 rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8640 if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8642 if (ent->animcache_vertex3f)
8644 r_refdef.stats[r_stat_batch_entitycache_count]++;
8645 r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8646 r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8647 r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8648 rsurface.modelvertex3f = ent->animcache_vertex3f;
8649 rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8650 rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8651 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8652 rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8653 rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8654 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8655 rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8656 rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8657 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8658 rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8659 rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8660 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8661 rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8662 rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8664 else if (wanttangents)
8666 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8667 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8668 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8669 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8670 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8671 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8672 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8673 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8674 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8675 rsurface.modelvertexmesh = NULL;
8676 rsurface.modelvertexmesh_vertexbuffer = NULL;
8677 rsurface.modelvertexmesh_bufferoffset = 0;
8678 rsurface.modelvertex3f_vertexbuffer = NULL;
8679 rsurface.modelvertex3f_bufferoffset = 0;
8680 rsurface.modelvertex3f_vertexbuffer = 0;
8681 rsurface.modelvertex3f_bufferoffset = 0;
8682 rsurface.modelsvector3f_vertexbuffer = 0;
8683 rsurface.modelsvector3f_bufferoffset = 0;
8684 rsurface.modeltvector3f_vertexbuffer = 0;
8685 rsurface.modeltvector3f_bufferoffset = 0;
8686 rsurface.modelnormal3f_vertexbuffer = 0;
8687 rsurface.modelnormal3f_bufferoffset = 0;
8689 else if (wantnormals)
8691 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8692 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8693 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8694 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8695 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8696 rsurface.modelsvector3f = NULL;
8697 rsurface.modeltvector3f = NULL;
8698 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8699 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8700 rsurface.modelvertexmesh = NULL;
8701 rsurface.modelvertexmesh_vertexbuffer = NULL;
8702 rsurface.modelvertexmesh_bufferoffset = 0;
8703 rsurface.modelvertex3f_vertexbuffer = NULL;
8704 rsurface.modelvertex3f_bufferoffset = 0;
8705 rsurface.modelvertex3f_vertexbuffer = 0;
8706 rsurface.modelvertex3f_bufferoffset = 0;
8707 rsurface.modelsvector3f_vertexbuffer = 0;
8708 rsurface.modelsvector3f_bufferoffset = 0;
8709 rsurface.modeltvector3f_vertexbuffer = 0;
8710 rsurface.modeltvector3f_bufferoffset = 0;
8711 rsurface.modelnormal3f_vertexbuffer = 0;
8712 rsurface.modelnormal3f_bufferoffset = 0;
8716 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8717 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8718 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8719 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8720 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8721 rsurface.modelsvector3f = NULL;
8722 rsurface.modeltvector3f = NULL;
8723 rsurface.modelnormal3f = NULL;
8724 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8725 rsurface.modelvertexmesh = NULL;
8726 rsurface.modelvertexmesh_vertexbuffer = NULL;
8727 rsurface.modelvertexmesh_bufferoffset = 0;
8728 rsurface.modelvertex3f_vertexbuffer = NULL;
8729 rsurface.modelvertex3f_bufferoffset = 0;
8730 rsurface.modelvertex3f_vertexbuffer = 0;
8731 rsurface.modelvertex3f_bufferoffset = 0;
8732 rsurface.modelsvector3f_vertexbuffer = 0;
8733 rsurface.modelsvector3f_bufferoffset = 0;
8734 rsurface.modeltvector3f_vertexbuffer = 0;
8735 rsurface.modeltvector3f_bufferoffset = 0;
8736 rsurface.modelnormal3f_vertexbuffer = 0;
8737 rsurface.modelnormal3f_bufferoffset = 0;
8739 rsurface.modelgeneratedvertex = true;
8743 if (rsurface.entityskeletaltransform3x4)
8745 r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8746 r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8747 r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8748 r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8752 r_refdef.stats[r_stat_batch_entitystatic_count]++;
8753 r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8754 r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8755 r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8757 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8758 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8759 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8760 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8761 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8762 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8763 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8764 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8765 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8766 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8767 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8768 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8769 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8770 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8771 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8772 rsurface.modelgeneratedvertex = false;
8774 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8775 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8776 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8777 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8778 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8779 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8780 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8781 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8782 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8783 rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8784 rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8785 rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8786 rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8787 rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8788 rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8789 rsurface.modelelement3i = model->surfmesh.data_element3i;
8790 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8791 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8792 rsurface.modelelement3s = model->surfmesh.data_element3s;
8793 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8794 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8795 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8796 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8797 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8798 rsurface.modelsurfaces = model->data_surfaces;
8799 rsurface.batchgeneratedvertex = false;
8800 rsurface.batchfirstvertex = 0;
8801 rsurface.batchnumvertices = 0;
8802 rsurface.batchfirsttriangle = 0;
8803 rsurface.batchnumtriangles = 0;
8804 rsurface.batchvertex3f = NULL;
8805 rsurface.batchvertex3f_vertexbuffer = NULL;
8806 rsurface.batchvertex3f_bufferoffset = 0;
8807 rsurface.batchsvector3f = NULL;
8808 rsurface.batchsvector3f_vertexbuffer = NULL;
8809 rsurface.batchsvector3f_bufferoffset = 0;
8810 rsurface.batchtvector3f = NULL;
8811 rsurface.batchtvector3f_vertexbuffer = NULL;
8812 rsurface.batchtvector3f_bufferoffset = 0;
8813 rsurface.batchnormal3f = NULL;
8814 rsurface.batchnormal3f_vertexbuffer = NULL;
8815 rsurface.batchnormal3f_bufferoffset = 0;
8816 rsurface.batchlightmapcolor4f = NULL;
8817 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8818 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8819 rsurface.batchtexcoordtexture2f = NULL;
8820 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8821 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8822 rsurface.batchtexcoordlightmap2f = NULL;
8823 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8824 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8825 rsurface.batchskeletalindex4ub = NULL;
8826 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8827 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8828 rsurface.batchskeletalweight4ub = NULL;
8829 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8830 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8831 rsurface.batchvertexmesh = NULL;
8832 rsurface.batchvertexmesh_vertexbuffer = NULL;
8833 rsurface.batchvertexmesh_bufferoffset = 0;
8834 rsurface.batchelement3i = NULL;
8835 rsurface.batchelement3i_indexbuffer = NULL;
8836 rsurface.batchelement3i_bufferoffset = 0;
8837 rsurface.batchelement3s = NULL;
8838 rsurface.batchelement3s_indexbuffer = NULL;
8839 rsurface.batchelement3s_bufferoffset = 0;
8840 rsurface.passcolor4f = NULL;
8841 rsurface.passcolor4f_vertexbuffer = NULL;
8842 rsurface.passcolor4f_bufferoffset = 0;
8843 rsurface.forcecurrenttextureupdate = false;
8846 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)
8848 rsurface.entity = r_refdef.scene.worldentity;
8849 rsurface.skeleton = NULL;
8850 rsurface.ent_skinnum = 0;
8851 rsurface.ent_qwskin = -1;
8852 rsurface.ent_flags = entflags;
8853 rsurface.shadertime = r_refdef.scene.time - shadertime;
8854 rsurface.modelnumvertices = numvertices;
8855 rsurface.modelnumtriangles = numtriangles;
8856 rsurface.matrix = *matrix;
8857 rsurface.inversematrix = *inversematrix;
8858 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8859 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8860 R_EntityMatrix(&rsurface.matrix);
8861 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8862 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8863 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8864 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8865 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8866 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8867 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8868 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8869 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8870 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8871 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8872 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8873 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);
8874 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8875 rsurface.frameblend[0].lerp = 1;
8876 rsurface.ent_alttextures = false;
8877 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8878 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8879 rsurface.entityskeletaltransform3x4 = NULL;
8880 rsurface.entityskeletaltransform3x4buffer = NULL;
8881 rsurface.entityskeletaltransform3x4offset = 0;
8882 rsurface.entityskeletaltransform3x4size = 0;
8883 rsurface.entityskeletalnumtransforms = 0;
8884 r_refdef.stats[r_stat_batch_entitycustom_count]++;
8885 r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8886 r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8887 r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8890 rsurface.modelvertex3f = (float *)vertex3f;
8891 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8892 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8893 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8895 else if (wantnormals)
8897 rsurface.modelvertex3f = (float *)vertex3f;
8898 rsurface.modelsvector3f = NULL;
8899 rsurface.modeltvector3f = NULL;
8900 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8904 rsurface.modelvertex3f = (float *)vertex3f;
8905 rsurface.modelsvector3f = NULL;
8906 rsurface.modeltvector3f = NULL;
8907 rsurface.modelnormal3f = NULL;
8909 rsurface.modelvertexmesh = NULL;
8910 rsurface.modelvertexmesh_vertexbuffer = NULL;
8911 rsurface.modelvertexmesh_bufferoffset = 0;
8912 rsurface.modelvertex3f_vertexbuffer = 0;
8913 rsurface.modelvertex3f_bufferoffset = 0;
8914 rsurface.modelsvector3f_vertexbuffer = 0;
8915 rsurface.modelsvector3f_bufferoffset = 0;
8916 rsurface.modeltvector3f_vertexbuffer = 0;
8917 rsurface.modeltvector3f_bufferoffset = 0;
8918 rsurface.modelnormal3f_vertexbuffer = 0;
8919 rsurface.modelnormal3f_bufferoffset = 0;
8920 rsurface.modelgeneratedvertex = true;
8921 rsurface.modellightmapcolor4f = (float *)color4f;
8922 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8923 rsurface.modellightmapcolor4f_bufferoffset = 0;
8924 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8925 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8926 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8927 rsurface.modeltexcoordlightmap2f = NULL;
8928 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8929 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8930 rsurface.modelskeletalindex4ub = NULL;
8931 rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8932 rsurface.modelskeletalindex4ub_bufferoffset = 0;
8933 rsurface.modelskeletalweight4ub = NULL;
8934 rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8935 rsurface.modelskeletalweight4ub_bufferoffset = 0;
8936 rsurface.modelelement3i = (int *)element3i;
8937 rsurface.modelelement3i_indexbuffer = NULL;
8938 rsurface.modelelement3i_bufferoffset = 0;
8939 rsurface.modelelement3s = (unsigned short *)element3s;
8940 rsurface.modelelement3s_indexbuffer = NULL;
8941 rsurface.modelelement3s_bufferoffset = 0;
8942 rsurface.modellightmapoffsets = NULL;
8943 rsurface.modelsurfaces = NULL;
8944 rsurface.batchgeneratedvertex = false;
8945 rsurface.batchfirstvertex = 0;
8946 rsurface.batchnumvertices = 0;
8947 rsurface.batchfirsttriangle = 0;
8948 rsurface.batchnumtriangles = 0;
8949 rsurface.batchvertex3f = NULL;
8950 rsurface.batchvertex3f_vertexbuffer = NULL;
8951 rsurface.batchvertex3f_bufferoffset = 0;
8952 rsurface.batchsvector3f = NULL;
8953 rsurface.batchsvector3f_vertexbuffer = NULL;
8954 rsurface.batchsvector3f_bufferoffset = 0;
8955 rsurface.batchtvector3f = NULL;
8956 rsurface.batchtvector3f_vertexbuffer = NULL;
8957 rsurface.batchtvector3f_bufferoffset = 0;
8958 rsurface.batchnormal3f = NULL;
8959 rsurface.batchnormal3f_vertexbuffer = NULL;
8960 rsurface.batchnormal3f_bufferoffset = 0;
8961 rsurface.batchlightmapcolor4f = NULL;
8962 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8963 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8964 rsurface.batchtexcoordtexture2f = NULL;
8965 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8966 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8967 rsurface.batchtexcoordlightmap2f = NULL;
8968 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8969 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8970 rsurface.batchskeletalindex4ub = NULL;
8971 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8972 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8973 rsurface.batchskeletalweight4ub = NULL;
8974 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8975 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8976 rsurface.batchvertexmesh = NULL;
8977 rsurface.batchvertexmesh_vertexbuffer = NULL;
8978 rsurface.batchvertexmesh_bufferoffset = 0;
8979 rsurface.batchelement3i = NULL;
8980 rsurface.batchelement3i_indexbuffer = NULL;
8981 rsurface.batchelement3i_bufferoffset = 0;
8982 rsurface.batchelement3s = NULL;
8983 rsurface.batchelement3s_indexbuffer = NULL;
8984 rsurface.batchelement3s_bufferoffset = 0;
8985 rsurface.passcolor4f = NULL;
8986 rsurface.passcolor4f_vertexbuffer = NULL;
8987 rsurface.passcolor4f_bufferoffset = 0;
8988 rsurface.forcecurrenttextureupdate = true;
8990 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8992 if ((wantnormals || wanttangents) && !normal3f)
8994 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8995 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8997 if (wanttangents && !svector3f)
8999 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9000 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9001 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
9006 float RSurf_FogPoint(const float *v)
9008 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9009 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9010 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9011 float FogHeightFade = r_refdef.fogheightfade;
9013 unsigned int fogmasktableindex;
9014 if (r_refdef.fogplaneviewabove)
9015 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9017 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9018 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9019 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9022 float RSurf_FogVertex(const float *v)
9024 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9025 float FogPlaneViewDist = rsurface.fogplaneviewdist;
9026 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9027 float FogHeightFade = rsurface.fogheightfade;
9029 unsigned int fogmasktableindex;
9030 if (r_refdef.fogplaneviewabove)
9031 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9033 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9034 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9035 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9038 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
9041 for (i = 0;i < numelements;i++)
9042 outelement3i[i] = inelement3i[i] + adjust;
9045 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9046 extern cvar_t gl_vbo;
9047 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9055 int surfacefirsttriangle;
9056 int surfacenumtriangles;
9057 int surfacefirstvertex;
9058 int surfaceendvertex;
9059 int surfacenumvertices;
9060 int batchnumsurfaces = texturenumsurfaces;
9061 int batchnumvertices;
9062 int batchnumtriangles;
9066 qboolean dynamicvertex;
9070 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9073 q3shaderinfo_deform_t *deform;
9074 const msurface_t *surface, *firstsurface;
9075 r_vertexmesh_t *vertexmesh;
9076 if (!texturenumsurfaces)
9078 // find vertex range of this surface batch
9080 firstsurface = texturesurfacelist[0];
9081 firsttriangle = firstsurface->num_firsttriangle;
9082 batchnumvertices = 0;
9083 batchnumtriangles = 0;
9084 firstvertex = endvertex = firstsurface->num_firstvertex;
9085 for (i = 0;i < texturenumsurfaces;i++)
9087 surface = texturesurfacelist[i];
9088 if (surface != firstsurface + i)
9090 surfacefirstvertex = surface->num_firstvertex;
9091 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
9092 surfacenumvertices = surface->num_vertices;
9093 surfacenumtriangles = surface->num_triangles;
9094 if (firstvertex > surfacefirstvertex)
9095 firstvertex = surfacefirstvertex;
9096 if (endvertex < surfaceendvertex)
9097 endvertex = surfaceendvertex;
9098 batchnumvertices += surfacenumvertices;
9099 batchnumtriangles += surfacenumtriangles;
9102 r_refdef.stats[r_stat_batch_batches]++;
9104 r_refdef.stats[r_stat_batch_withgaps]++;
9105 r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
9106 r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
9107 r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
9109 // we now know the vertex range used, and if there are any gaps in it
9110 rsurface.batchfirstvertex = firstvertex;
9111 rsurface.batchnumvertices = endvertex - firstvertex;
9112 rsurface.batchfirsttriangle = firsttriangle;
9113 rsurface.batchnumtriangles = batchnumtriangles;
9115 // this variable holds flags for which properties have been updated that
9116 // may require regenerating vertexmesh array...
9119 // check if any dynamic vertex processing must occur
9120 dynamicvertex = false;
9122 // a cvar to force the dynamic vertex path to be taken, for debugging
9123 if (r_batch_debugdynamicvertexpath.integer)
9127 r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9128 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9129 r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9130 r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9132 dynamicvertex = true;
9135 // if there is a chance of animated vertex colors, it's a dynamic batch
9136 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9140 r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9141 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9142 r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9143 r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9145 dynamicvertex = true;
9146 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9149 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9151 switch (deform->deform)
9154 case Q3DEFORM_PROJECTIONSHADOW:
9155 case Q3DEFORM_TEXT0:
9156 case Q3DEFORM_TEXT1:
9157 case Q3DEFORM_TEXT2:
9158 case Q3DEFORM_TEXT3:
9159 case Q3DEFORM_TEXT4:
9160 case Q3DEFORM_TEXT5:
9161 case Q3DEFORM_TEXT6:
9162 case Q3DEFORM_TEXT7:
9165 case Q3DEFORM_AUTOSPRITE:
9168 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9169 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9170 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9171 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9173 dynamicvertex = true;
9174 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9175 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9177 case Q3DEFORM_AUTOSPRITE2:
9180 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9181 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9182 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9183 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9185 dynamicvertex = true;
9186 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9187 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9189 case Q3DEFORM_NORMAL:
9192 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9193 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9194 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9195 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9197 dynamicvertex = true;
9198 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9199 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9202 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9203 break; // if wavefunc is a nop, ignore this transform
9206 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9207 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9208 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9209 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9211 dynamicvertex = true;
9212 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9213 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9215 case Q3DEFORM_BULGE:
9218 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9219 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9220 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9221 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9223 dynamicvertex = true;
9224 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9225 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9228 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9229 break; // if wavefunc is a nop, ignore this transform
9232 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9233 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9234 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9235 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9237 dynamicvertex = true;
9238 batchneed |= BATCHNEED_ARRAY_VERTEX;
9239 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9243 switch(rsurface.texture->tcgen.tcgen)
9246 case Q3TCGEN_TEXTURE:
9248 case Q3TCGEN_LIGHTMAP:
9251 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9252 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9253 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9254 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9256 dynamicvertex = true;
9257 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9258 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9260 case Q3TCGEN_VECTOR:
9263 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9264 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9265 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9266 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9268 dynamicvertex = true;
9269 batchneed |= BATCHNEED_ARRAY_VERTEX;
9270 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9272 case Q3TCGEN_ENVIRONMENT:
9275 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9276 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9277 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9278 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9280 dynamicvertex = true;
9281 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9282 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9285 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9289 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9290 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9291 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9292 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9294 dynamicvertex = true;
9295 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9296 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9299 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9303 r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9304 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9305 r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9306 r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9308 dynamicvertex = true;
9309 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9312 // when the model data has no vertex buffer (dynamic mesh), we need to
9314 if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9315 batchneed |= BATCHNEED_NOGAPS;
9317 // the caller can specify BATCHNEED_NOGAPS to force a batch with
9318 // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9319 // we ensure this by treating the vertex batch as dynamic...
9320 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9324 r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9325 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9326 r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9327 r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9329 dynamicvertex = true;
9334 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9335 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
9336 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
9337 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
9338 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9339 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9340 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9341 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL) batchneed |= BATCHNEED_ARRAY_SKELETAL;
9344 // if needsupdate, we have to do a dynamic vertex batch for sure
9345 if (needsupdate & batchneed)
9349 r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9350 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9351 r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9352 r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9354 dynamicvertex = true;
9357 // see if we need to build vertexmesh from arrays
9358 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9362 r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9363 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9364 r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9365 r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9367 dynamicvertex = true;
9370 // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9371 if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9372 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9374 rsurface.batchvertex3f = rsurface.modelvertex3f;
9375 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9376 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9377 rsurface.batchsvector3f = rsurface.modelsvector3f;
9378 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9379 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9380 rsurface.batchtvector3f = rsurface.modeltvector3f;
9381 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9382 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9383 rsurface.batchnormal3f = rsurface.modelnormal3f;
9384 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9385 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9386 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9387 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
9388 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
9389 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9390 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
9391 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
9392 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9393 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9394 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9395 rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9396 rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9397 rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9398 rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9399 rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9400 rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9401 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9402 rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9403 rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9404 rsurface.batchelement3i = rsurface.modelelement3i;
9405 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9406 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9407 rsurface.batchelement3s = rsurface.modelelement3s;
9408 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9409 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9410 rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9411 rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9412 rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9413 rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9414 rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9416 // if any dynamic vertex processing has to occur in software, we copy the
9417 // entire surface list together before processing to rebase the vertices
9418 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9420 // if any gaps exist and we do not have a static vertex buffer, we have to
9421 // copy the surface list together to avoid wasting upload bandwidth on the
9422 // vertices in the gaps.
9424 // if gaps exist and we have a static vertex buffer, we can choose whether
9425 // to combine the index buffer ranges into one dynamic index buffer or
9426 // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9428 // in many cases the batch is reduced to one draw call.
9430 rsurface.batchmultidraw = false;
9431 rsurface.batchmultidrawnumsurfaces = 0;
9432 rsurface.batchmultidrawsurfacelist = NULL;
9436 // static vertex data, just set pointers...
9437 rsurface.batchgeneratedvertex = false;
9438 // if there are gaps, we want to build a combined index buffer,
9439 // otherwise use the original static buffer with an appropriate offset
9442 r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9443 r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9444 r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9445 r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9446 if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9448 rsurface.batchmultidraw = true;
9449 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9450 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9453 // build a new triangle elements array for this batch
9454 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9455 rsurface.batchfirsttriangle = 0;
9457 for (i = 0;i < texturenumsurfaces;i++)
9459 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9460 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9461 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9462 numtriangles += surfacenumtriangles;
9464 rsurface.batchelement3i_indexbuffer = NULL;
9465 rsurface.batchelement3i_bufferoffset = 0;
9466 rsurface.batchelement3s = NULL;
9467 rsurface.batchelement3s_indexbuffer = NULL;
9468 rsurface.batchelement3s_bufferoffset = 0;
9469 if (endvertex <= 65536)
9471 // make a 16bit (unsigned short) index array if possible
9472 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9473 for (i = 0;i < numtriangles*3;i++)
9474 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9476 // upload buffer data for the copytriangles batch
9477 if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9479 if (rsurface.batchelement3s)
9480 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9481 else if (rsurface.batchelement3i)
9482 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9487 r_refdef.stats[r_stat_batch_fast_batches] += 1;
9488 r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9489 r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9490 r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9495 // something needs software processing, do it for real...
9496 // we only directly handle separate array data in this case and then
9497 // generate interleaved data if needed...
9498 rsurface.batchgeneratedvertex = true;
9499 r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9500 r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9501 r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9502 r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9504 // now copy the vertex data into a combined array and make an index array
9505 // (this is what Quake3 does all the time)
9506 // we also apply any skeletal animation here that would have been done in
9507 // the vertex shader, because most of the dynamic vertex animation cases
9508 // need actual vertex positions and normals
9509 //if (dynamicvertex)
9511 rsurface.batchvertexmesh = NULL;
9512 rsurface.batchvertexmesh_vertexbuffer = NULL;
9513 rsurface.batchvertexmesh_bufferoffset = 0;
9514 rsurface.batchvertex3f = NULL;
9515 rsurface.batchvertex3f_vertexbuffer = NULL;
9516 rsurface.batchvertex3f_bufferoffset = 0;
9517 rsurface.batchsvector3f = NULL;
9518 rsurface.batchsvector3f_vertexbuffer = NULL;
9519 rsurface.batchsvector3f_bufferoffset = 0;
9520 rsurface.batchtvector3f = NULL;
9521 rsurface.batchtvector3f_vertexbuffer = NULL;
9522 rsurface.batchtvector3f_bufferoffset = 0;
9523 rsurface.batchnormal3f = NULL;
9524 rsurface.batchnormal3f_vertexbuffer = NULL;
9525 rsurface.batchnormal3f_bufferoffset = 0;
9526 rsurface.batchlightmapcolor4f = NULL;
9527 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9528 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9529 rsurface.batchtexcoordtexture2f = NULL;
9530 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9531 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9532 rsurface.batchtexcoordlightmap2f = NULL;
9533 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9534 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9535 rsurface.batchskeletalindex4ub = NULL;
9536 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9537 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9538 rsurface.batchskeletalweight4ub = NULL;
9539 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9540 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9541 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9542 rsurface.batchelement3i_indexbuffer = NULL;
9543 rsurface.batchelement3i_bufferoffset = 0;
9544 rsurface.batchelement3s = NULL;
9545 rsurface.batchelement3s_indexbuffer = NULL;
9546 rsurface.batchelement3s_bufferoffset = 0;
9547 rsurface.batchskeletaltransform3x4buffer = NULL;
9548 rsurface.batchskeletaltransform3x4offset = 0;
9549 rsurface.batchskeletaltransform3x4size = 0;
9550 // we'll only be setting up certain arrays as needed
9551 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9552 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9553 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9554 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9555 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9556 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9557 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9559 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9560 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9562 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9563 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9564 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9565 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9566 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9567 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9568 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9570 rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9571 rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9575 for (i = 0;i < texturenumsurfaces;i++)
9577 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9578 surfacenumvertices = texturesurfacelist[i]->num_vertices;
9579 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9580 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9581 // copy only the data requested
9582 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9583 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9584 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9586 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9588 if (rsurface.batchvertex3f)
9589 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9591 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9593 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9595 if (rsurface.modelnormal3f)
9596 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9598 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9600 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9602 if (rsurface.modelsvector3f)
9604 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9605 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9609 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9610 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9613 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9615 if (rsurface.modellightmapcolor4f)
9616 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9618 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9620 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9622 if (rsurface.modeltexcoordtexture2f)
9623 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9625 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9627 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9629 if (rsurface.modeltexcoordlightmap2f)
9630 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9632 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9634 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9636 if (rsurface.modelskeletalindex4ub)
9638 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9639 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9643 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9644 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9645 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9646 for (j = 0;j < surfacenumvertices;j++)
9651 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9652 numvertices += surfacenumvertices;
9653 numtriangles += surfacenumtriangles;
9656 // generate a 16bit index array as well if possible
9657 // (in general, dynamic batches fit)
9658 if (numvertices <= 65536)
9660 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9661 for (i = 0;i < numtriangles*3;i++)
9662 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9665 // since we've copied everything, the batch now starts at 0
9666 rsurface.batchfirstvertex = 0;
9667 rsurface.batchnumvertices = batchnumvertices;
9668 rsurface.batchfirsttriangle = 0;
9669 rsurface.batchnumtriangles = batchnumtriangles;
9672 // apply skeletal animation that would have been done in the vertex shader
9673 if (rsurface.batchskeletaltransform3x4)
9675 const unsigned char *si;
9676 const unsigned char *sw;
9678 const float *b = rsurface.batchskeletaltransform3x4;
9679 float *vp, *vs, *vt, *vn;
9681 float m[3][4], n[3][4];
9682 float tp[3], ts[3], tt[3], tn[3];
9683 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9684 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9685 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9686 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9687 si = rsurface.batchskeletalindex4ub;
9688 sw = rsurface.batchskeletalweight4ub;
9689 vp = rsurface.batchvertex3f;
9690 vs = rsurface.batchsvector3f;
9691 vt = rsurface.batchtvector3f;
9692 vn = rsurface.batchnormal3f;
9693 memset(m[0], 0, sizeof(m));
9694 memset(n[0], 0, sizeof(n));
9695 for (i = 0;i < batchnumvertices;i++)
9697 t[0] = b + si[0]*12;
9700 // common case - only one matrix
9714 else if (sw[2] + sw[3])
9717 t[1] = b + si[1]*12;
9718 t[2] = b + si[2]*12;
9719 t[3] = b + si[3]*12;
9720 w[0] = sw[0] * (1.0f / 255.0f);
9721 w[1] = sw[1] * (1.0f / 255.0f);
9722 w[2] = sw[2] * (1.0f / 255.0f);
9723 w[3] = sw[3] * (1.0f / 255.0f);
9724 // blend the matrices
9725 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9726 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9727 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9728 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9729 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9730 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9731 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9732 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9733 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9734 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9735 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9736 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9741 t[1] = b + si[1]*12;
9742 w[0] = sw[0] * (1.0f / 255.0f);
9743 w[1] = sw[1] * (1.0f / 255.0f);
9744 // blend the matrices
9745 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9746 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9747 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9748 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9749 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9750 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9751 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9752 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9753 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9754 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9755 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9756 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9760 // modify the vertex
9762 vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9763 vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9764 vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9768 // the normal transformation matrix is a set of cross products...
9769 CrossProduct(m[1], m[2], n[0]);
9770 CrossProduct(m[2], m[0], n[1]);
9771 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9773 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9774 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9775 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9776 VectorNormalize(vn);
9781 vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9782 vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9783 vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9784 VectorNormalize(vs);
9787 vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9788 vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9789 vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9790 VectorNormalize(vt);
9795 rsurface.batchskeletaltransform3x4 = NULL;
9796 rsurface.batchskeletalnumtransforms = 0;
9799 // q1bsp surfaces rendered in vertex color mode have to have colors
9800 // calculated based on lightstyles
9801 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9803 // generate color arrays for the surfaces in this list
9808 const unsigned char *lm;
9809 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9810 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9811 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9813 for (i = 0;i < texturenumsurfaces;i++)
9815 surface = texturesurfacelist[i];
9816 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9817 surfacenumvertices = surface->num_vertices;
9818 if (surface->lightmapinfo->samples)
9820 for (j = 0;j < surfacenumvertices;j++)
9822 lm = surface->lightmapinfo->samples + offsets[j];
9823 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9824 VectorScale(lm, scale, c);
9825 if (surface->lightmapinfo->styles[1] != 255)
9827 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9829 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9830 VectorMA(c, scale, lm, c);
9831 if (surface->lightmapinfo->styles[2] != 255)
9834 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9835 VectorMA(c, scale, lm, c);
9836 if (surface->lightmapinfo->styles[3] != 255)
9839 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9840 VectorMA(c, scale, lm, c);
9847 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);
9853 for (j = 0;j < surfacenumvertices;j++)
9855 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9862 // if vertices are deformed (sprite flares and things in maps, possibly
9863 // water waves, bulges and other deformations), modify the copied vertices
9865 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9867 switch (deform->deform)
9870 case Q3DEFORM_PROJECTIONSHADOW:
9871 case Q3DEFORM_TEXT0:
9872 case Q3DEFORM_TEXT1:
9873 case Q3DEFORM_TEXT2:
9874 case Q3DEFORM_TEXT3:
9875 case Q3DEFORM_TEXT4:
9876 case Q3DEFORM_TEXT5:
9877 case Q3DEFORM_TEXT6:
9878 case Q3DEFORM_TEXT7:
9881 case Q3DEFORM_AUTOSPRITE:
9882 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9883 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9884 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9885 VectorNormalize(newforward);
9886 VectorNormalize(newright);
9887 VectorNormalize(newup);
9888 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9889 // rsurface.batchvertex3f_vertexbuffer = NULL;
9890 // rsurface.batchvertex3f_bufferoffset = 0;
9891 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9892 // rsurface.batchsvector3f_vertexbuffer = NULL;
9893 // rsurface.batchsvector3f_bufferoffset = 0;
9894 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9895 // rsurface.batchtvector3f_vertexbuffer = NULL;
9896 // rsurface.batchtvector3f_bufferoffset = 0;
9897 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9898 // rsurface.batchnormal3f_vertexbuffer = NULL;
9899 // rsurface.batchnormal3f_bufferoffset = 0;
9900 // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9901 if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9902 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9903 if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9904 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 // a single autosprite surface can contain multiple sprites...
9906 for (j = 0;j < batchnumvertices - 3;j += 4)
9908 VectorClear(center);
9909 for (i = 0;i < 4;i++)
9910 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9911 VectorScale(center, 0.25f, center);
9912 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9913 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9914 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9915 for (i = 0;i < 4;i++)
9917 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9918 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9921 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9922 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9923 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);
9925 case Q3DEFORM_AUTOSPRITE2:
9926 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9927 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9928 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9929 VectorNormalize(newforward);
9930 VectorNormalize(newright);
9931 VectorNormalize(newup);
9932 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9933 // rsurface.batchvertex3f_vertexbuffer = NULL;
9934 // rsurface.batchvertex3f_bufferoffset = 0;
9936 const float *v1, *v2;
9946 memset(shortest, 0, sizeof(shortest));
9947 // a single autosprite surface can contain multiple sprites...
9948 for (j = 0;j < batchnumvertices - 3;j += 4)
9950 VectorClear(center);
9951 for (i = 0;i < 4;i++)
9952 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9953 VectorScale(center, 0.25f, center);
9954 // find the two shortest edges, then use them to define the
9955 // axis vectors for rotating around the central axis
9956 for (i = 0;i < 6;i++)
9958 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9959 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9960 l = VectorDistance2(v1, v2);
9961 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9963 l += (1.0f / 1024.0f);
9964 if (shortest[0].length2 > l || i == 0)
9966 shortest[1] = shortest[0];
9967 shortest[0].length2 = l;
9968 shortest[0].v1 = v1;
9969 shortest[0].v2 = v2;
9971 else if (shortest[1].length2 > l || i == 1)
9973 shortest[1].length2 = l;
9974 shortest[1].v1 = v1;
9975 shortest[1].v2 = v2;
9978 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9979 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9980 // this calculates the right vector from the shortest edge
9981 // and the up vector from the edge midpoints
9982 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9983 VectorNormalize(right);
9984 VectorSubtract(end, start, up);
9985 VectorNormalize(up);
9986 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9987 VectorSubtract(rsurface.localvieworigin, center, forward);
9988 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9989 VectorNegate(forward, forward);
9990 VectorReflect(forward, 0, up, forward);
9991 VectorNormalize(forward);
9992 CrossProduct(up, forward, newright);
9993 VectorNormalize(newright);
9994 // rotate the quad around the up axis vector, this is made
9995 // especially easy by the fact we know the quad is flat,
9996 // so we only have to subtract the center position and
9997 // measure distance along the right vector, and then
9998 // multiply that by the newright vector and add back the
10000 // we also need to subtract the old position to undo the
10001 // displacement from the center, which we do with a
10002 // DotProduct, the subtraction/addition of center is also
10003 // optimized into DotProducts here
10004 l = DotProduct(right, center);
10005 for (i = 0;i < 4;i++)
10007 v1 = rsurface.batchvertex3f + 3*(j+i);
10008 f = DotProduct(right, v1) - l;
10009 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
10013 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
10015 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10016 // rsurface.batchnormal3f_vertexbuffer = NULL;
10017 // rsurface.batchnormal3f_bufferoffset = 0;
10018 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10020 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10022 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10023 // rsurface.batchsvector3f_vertexbuffer = NULL;
10024 // rsurface.batchsvector3f_bufferoffset = 0;
10025 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10026 // rsurface.batchtvector3f_vertexbuffer = NULL;
10027 // rsurface.batchtvector3f_bufferoffset = 0;
10028 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);
10031 case Q3DEFORM_NORMAL:
10032 // deform the normals to make reflections wavey
10033 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10034 rsurface.batchnormal3f_vertexbuffer = NULL;
10035 rsurface.batchnormal3f_bufferoffset = 0;
10036 for (j = 0;j < batchnumvertices;j++)
10039 float *normal = rsurface.batchnormal3f + 3*j;
10040 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
10041 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10042 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10043 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10044 VectorNormalize(normal);
10046 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10048 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10049 // rsurface.batchsvector3f_vertexbuffer = NULL;
10050 // rsurface.batchsvector3f_bufferoffset = 0;
10051 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10052 // rsurface.batchtvector3f_vertexbuffer = NULL;
10053 // rsurface.batchtvector3f_bufferoffset = 0;
10054 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);
10057 case Q3DEFORM_WAVE:
10058 // deform vertex array to make wavey water and flags and such
10059 waveparms[0] = deform->waveparms[0];
10060 waveparms[1] = deform->waveparms[1];
10061 waveparms[2] = deform->waveparms[2];
10062 waveparms[3] = deform->waveparms[3];
10063 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
10064 break; // if wavefunc is a nop, don't make a dynamic vertex array
10065 // this is how a divisor of vertex influence on deformation
10066 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10067 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10068 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10069 // rsurface.batchvertex3f_vertexbuffer = NULL;
10070 // rsurface.batchvertex3f_bufferoffset = 0;
10071 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10072 // rsurface.batchnormal3f_vertexbuffer = NULL;
10073 // rsurface.batchnormal3f_bufferoffset = 0;
10074 for (j = 0;j < batchnumvertices;j++)
10076 // if the wavefunc depends on time, evaluate it per-vertex
10079 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
10080 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10082 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10084 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10085 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10086 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10088 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10089 // rsurface.batchsvector3f_vertexbuffer = NULL;
10090 // rsurface.batchsvector3f_bufferoffset = 0;
10091 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10092 // rsurface.batchtvector3f_vertexbuffer = NULL;
10093 // rsurface.batchtvector3f_bufferoffset = 0;
10094 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);
10097 case Q3DEFORM_BULGE:
10098 // deform vertex array to make the surface have moving bulges
10099 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10100 // rsurface.batchvertex3f_vertexbuffer = NULL;
10101 // rsurface.batchvertex3f_bufferoffset = 0;
10102 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10103 // rsurface.batchnormal3f_vertexbuffer = NULL;
10104 // rsurface.batchnormal3f_bufferoffset = 0;
10105 for (j = 0;j < batchnumvertices;j++)
10107 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
10108 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10110 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10111 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10112 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10114 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10115 // rsurface.batchsvector3f_vertexbuffer = NULL;
10116 // rsurface.batchsvector3f_bufferoffset = 0;
10117 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10118 // rsurface.batchtvector3f_vertexbuffer = NULL;
10119 // rsurface.batchtvector3f_bufferoffset = 0;
10120 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);
10123 case Q3DEFORM_MOVE:
10124 // deform vertex array
10125 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10126 break; // if wavefunc is a nop, don't make a dynamic vertex array
10127 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10128 VectorScale(deform->parms, scale, waveparms);
10129 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10130 // rsurface.batchvertex3f_vertexbuffer = NULL;
10131 // rsurface.batchvertex3f_bufferoffset = 0;
10132 for (j = 0;j < batchnumvertices;j++)
10133 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10138 if (rsurface.batchtexcoordtexture2f)
10140 // generate texcoords based on the chosen texcoord source
10141 switch(rsurface.texture->tcgen.tcgen)
10144 case Q3TCGEN_TEXTURE:
10146 case Q3TCGEN_LIGHTMAP:
10147 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10148 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10149 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10150 if (rsurface.batchtexcoordlightmap2f)
10151 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
10153 case Q3TCGEN_VECTOR:
10154 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10155 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10156 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10157 for (j = 0;j < batchnumvertices;j++)
10159 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
10160 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
10163 case Q3TCGEN_ENVIRONMENT:
10164 // make environment reflections using a spheremap
10165 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10166 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10167 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10168 for (j = 0;j < batchnumvertices;j++)
10170 // identical to Q3A's method, but executed in worldspace so
10171 // carried models can be shiny too
10173 float viewer[3], d, reflected[3], worldreflected[3];
10175 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10176 // VectorNormalize(viewer);
10178 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10180 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10181 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10182 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10183 // note: this is proportinal to viewer, so we can normalize later
10185 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10186 VectorNormalize(worldreflected);
10188 // note: this sphere map only uses world x and z!
10189 // so positive and negative y will LOOK THE SAME.
10190 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10191 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10195 // the only tcmod that needs software vertex processing is turbulent, so
10196 // check for it here and apply the changes if needed
10197 // and we only support that as the first one
10198 // (handling a mixture of turbulent and other tcmods would be problematic
10199 // without punting it entirely to a software path)
10200 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10202 amplitude = rsurface.texture->tcmods[0].parms[1];
10203 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
10204 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10205 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10206 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10207 for (j = 0;j < batchnumvertices;j++)
10209 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);
10210 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10215 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10217 // convert the modified arrays to vertex structs
10218 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10219 // rsurface.batchvertexmesh_vertexbuffer = NULL;
10220 // rsurface.batchvertexmesh_bufferoffset = 0;
10221 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10222 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10223 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10224 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10225 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10226 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10227 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10229 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10231 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10232 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10235 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10236 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10237 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10238 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10239 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10240 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10241 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10242 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10243 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10244 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10246 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10248 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10249 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10254 // upload buffer data for the dynamic batch
10255 if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10257 if (rsurface.batchvertexmesh)
10258 rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10261 if (rsurface.batchvertex3f)
10262 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10263 if (rsurface.batchsvector3f)
10264 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10265 if (rsurface.batchtvector3f)
10266 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10267 if (rsurface.batchnormal3f)
10268 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10269 if (rsurface.batchlightmapcolor4f)
10270 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10271 if (rsurface.batchtexcoordtexture2f)
10272 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10273 if (rsurface.batchtexcoordlightmap2f)
10274 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10275 if (rsurface.batchskeletalindex4ub)
10276 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10277 if (rsurface.batchskeletalweight4ub)
10278 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10280 if (rsurface.batchelement3s)
10281 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10282 else if (rsurface.batchelement3i)
10283 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10287 void RSurf_DrawBatch(void)
10289 // sometimes a zero triangle surface (usually a degenerate patch) makes it
10290 // through the pipeline, killing it earlier in the pipeline would have
10291 // per-surface overhead rather than per-batch overhead, so it's best to
10292 // reject it here, before it hits glDraw.
10293 if (rsurface.batchnumtriangles == 0)
10296 // batch debugging code
10297 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10303 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10304 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10307 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10309 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10311 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10312 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);
10319 if (rsurface.batchmultidraw)
10321 // issue multiple draws rather than copying index data
10322 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10323 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10324 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10325 for (i = 0;i < numsurfaces;)
10327 // combine consecutive surfaces as one draw
10328 for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10329 if (surfacelist[j] != surfacelist[k] + 1)
10331 firstvertex = surfacelist[i]->num_firstvertex;
10332 endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10333 firsttriangle = surfacelist[i]->num_firsttriangle;
10334 endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10335 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);
10341 // there is only one consecutive run of index data (may have been combined)
10342 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);
10346 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10348 // pick the closest matching water plane
10349 int planeindex, vertexindex, bestplaneindex = -1;
10353 r_waterstate_waterplane_t *p;
10354 qboolean prepared = false;
10356 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10358 if(p->camera_entity != rsurface.texture->camera_entity)
10363 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10365 if(rsurface.batchnumvertices == 0)
10368 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10370 Matrix4x4_Transform(&rsurface.matrix, v, vert);
10371 d += fabs(PlaneDiff(vert, &p->plane));
10373 if (bestd > d || bestplaneindex < 0)
10376 bestplaneindex = planeindex;
10379 return bestplaneindex;
10380 // NOTE: this MAY return a totally unrelated water plane; we can ignore
10381 // this situation though, as it might be better to render single larger
10382 // batches with useless stuff (backface culled for example) than to
10383 // render multiple smaller batches
10386 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10389 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10390 rsurface.passcolor4f_vertexbuffer = 0;
10391 rsurface.passcolor4f_bufferoffset = 0;
10392 for (i = 0;i < rsurface.batchnumvertices;i++)
10393 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10396 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10403 if (rsurface.passcolor4f)
10405 // generate color arrays
10406 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10407 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10408 rsurface.passcolor4f_vertexbuffer = 0;
10409 rsurface.passcolor4f_bufferoffset = 0;
10410 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)
10412 f = RSurf_FogVertex(v);
10421 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10422 rsurface.passcolor4f_vertexbuffer = 0;
10423 rsurface.passcolor4f_bufferoffset = 0;
10424 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10426 f = RSurf_FogVertex(v);
10435 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10442 if (!rsurface.passcolor4f)
10444 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10445 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10446 rsurface.passcolor4f_vertexbuffer = 0;
10447 rsurface.passcolor4f_bufferoffset = 0;
10448 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)
10450 f = RSurf_FogVertex(v);
10451 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10452 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10453 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10458 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
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)
10478 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10483 if (!rsurface.passcolor4f)
10485 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10486 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10487 rsurface.passcolor4f_vertexbuffer = 0;
10488 rsurface.passcolor4f_bufferoffset = 0;
10489 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10491 c2[0] = c[0] + r_refdef.scene.ambient;
10492 c2[1] = c[1] + r_refdef.scene.ambient;
10493 c2[2] = c[2] + r_refdef.scene.ambient;
10498 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10501 rsurface.passcolor4f = NULL;
10502 rsurface.passcolor4f_vertexbuffer = 0;
10503 rsurface.passcolor4f_bufferoffset = 0;
10504 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10505 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10506 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10507 GL_Color(r, g, b, a);
10508 R_Mesh_TexBind(0, rsurface.lightmaptexture);
10509 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10510 R_Mesh_TexMatrix(0, NULL);
10514 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10516 // TODO: optimize applyfog && applycolor case
10517 // just apply fog if necessary, and tint the fog color array if necessary
10518 rsurface.passcolor4f = NULL;
10519 rsurface.passcolor4f_vertexbuffer = 0;
10520 rsurface.passcolor4f_bufferoffset = 0;
10521 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10522 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10523 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10524 GL_Color(r, g, b, a);
10528 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10531 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10532 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10533 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10534 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10535 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10536 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10537 GL_Color(r, g, b, a);
10541 static void RSurf_DrawBatch_GL11_ClampColor(void)
10546 if (!rsurface.passcolor4f)
10548 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10550 c2[0] = bound(0.0f, c1[0], 1.0f);
10551 c2[1] = bound(0.0f, c1[1], 1.0f);
10552 c2[2] = bound(0.0f, c1[2], 1.0f);
10553 c2[3] = bound(0.0f, c1[3], 1.0f);
10557 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10567 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10568 rsurface.passcolor4f_vertexbuffer = 0;
10569 rsurface.passcolor4f_bufferoffset = 0;
10570 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)
10572 f = -DotProduct(r_refdef.view.forward, n);
10574 f = f * 0.85 + 0.15; // work around so stuff won't get black
10575 f *= r_refdef.lightmapintensity;
10576 Vector4Set(c, f, f, f, 1);
10580 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10582 RSurf_DrawBatch_GL11_ApplyFakeLight();
10583 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10584 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10585 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10586 GL_Color(r, g, b, a);
10590 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10598 vec3_t ambientcolor;
10599 vec3_t diffusecolor;
10603 VectorCopy(rsurface.modellight_lightdir, lightdir);
10604 f = 0.5f * r_refdef.lightmapintensity;
10605 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10606 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10607 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10608 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10609 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10610 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10612 if (VectorLength2(diffusecolor) > 0)
10614 // q3-style directional shading
10615 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10616 rsurface.passcolor4f_vertexbuffer = 0;
10617 rsurface.passcolor4f_bufferoffset = 0;
10618 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)
10620 if ((f = DotProduct(n, lightdir)) > 0)
10621 VectorMA(ambientcolor, f, diffusecolor, c);
10623 VectorCopy(ambientcolor, c);
10630 *applycolor = false;
10634 *r = ambientcolor[0];
10635 *g = ambientcolor[1];
10636 *b = ambientcolor[2];
10637 rsurface.passcolor4f = NULL;
10638 rsurface.passcolor4f_vertexbuffer = 0;
10639 rsurface.passcolor4f_bufferoffset = 0;
10643 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10645 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10646 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10647 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10648 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10649 GL_Color(r, g, b, a);
10653 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10661 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10662 rsurface.passcolor4f_vertexbuffer = 0;
10663 rsurface.passcolor4f_bufferoffset = 0;
10665 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10667 f = 1 - RSurf_FogVertex(v);
10675 void RSurf_SetupDepthAndCulling(void)
10677 // submodels are biased to avoid z-fighting with world surfaces that they
10678 // may be exactly overlapping (avoids z-fighting artifacts on certain
10679 // doors and things in Quake maps)
10680 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10681 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10682 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10683 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10686 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10688 // transparent sky would be ridiculous
10689 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10691 R_SetupShader_Generic_NoTexture(false, false);
10692 skyrenderlater = true;
10693 RSurf_SetupDepthAndCulling();
10694 GL_DepthMask(true);
10695 // LordHavoc: HalfLife maps have freaky skypolys so don't use
10696 // skymasking on them, and Quake3 never did sky masking (unlike
10697 // software Quake and software Quake2), so disable the sky masking
10698 // in Quake3 maps as it causes problems with q3map2 sky tricks,
10699 // and skymasking also looks very bad when noclipping outside the
10700 // level, so don't use it then either.
10701 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.skymasking && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10703 R_Mesh_ResetTextureState();
10704 if (skyrendermasked)
10706 R_SetupShader_DepthOrShadow(false, false, false);
10707 // depth-only (masking)
10708 GL_ColorMask(0,0,0,0);
10709 // just to make sure that braindead drivers don't draw
10710 // anything despite that colormask...
10711 GL_BlendFunc(GL_ZERO, GL_ONE);
10712 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10713 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10717 R_SetupShader_Generic_NoTexture(false, false);
10719 GL_BlendFunc(GL_ONE, GL_ZERO);
10720 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10721 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10722 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10725 if (skyrendermasked)
10726 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10728 R_Mesh_ResetTextureState();
10729 GL_Color(1, 1, 1, 1);
10732 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10733 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10734 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10736 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10740 // render screenspace normalmap to texture
10741 GL_DepthMask(true);
10742 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10747 // bind lightmap texture
10749 // water/refraction/reflection/camera surfaces have to be handled specially
10750 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10752 int start, end, startplaneindex;
10753 for (start = 0;start < texturenumsurfaces;start = end)
10755 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10756 if(startplaneindex < 0)
10758 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10759 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10763 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10765 // now that we have a batch using the same planeindex, render it
10766 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10768 // render water or distortion background
10769 GL_DepthMask(true);
10770 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);
10772 // blend surface on top
10773 GL_DepthMask(false);
10774 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10777 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10779 // render surface with reflection texture as input
10780 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10781 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);
10788 // render surface batch normally
10789 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10790 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);
10794 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10796 // OpenGL 1.3 path - anything not completely ancient
10797 qboolean applycolor;
10800 const texturelayer_t *layer;
10801 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);
10802 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10804 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10807 int layertexrgbscale;
10808 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10810 if (layerindex == 0)
10811 GL_AlphaTest(true);
10814 GL_AlphaTest(false);
10815 GL_DepthFunc(GL_EQUAL);
10818 GL_DepthMask(layer->depthmask && writedepth);
10819 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10820 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10822 layertexrgbscale = 4;
10823 VectorScale(layer->color, 0.25f, layercolor);
10825 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10827 layertexrgbscale = 2;
10828 VectorScale(layer->color, 0.5f, layercolor);
10832 layertexrgbscale = 1;
10833 VectorScale(layer->color, 1.0f, layercolor);
10835 layercolor[3] = layer->color[3];
10836 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10837 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10838 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10839 switch (layer->type)
10841 case TEXTURELAYERTYPE_LITTEXTURE:
10842 // single-pass lightmapped texture with 2x rgbscale
10843 R_Mesh_TexBind(0, r_texture_white);
10844 R_Mesh_TexMatrix(0, NULL);
10845 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10846 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10847 R_Mesh_TexBind(1, layer->texture);
10848 R_Mesh_TexMatrix(1, &layer->texmatrix);
10849 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10850 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10851 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10852 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10853 else if (FAKELIGHT_ENABLED)
10854 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10855 else if (rsurface.uselightmaptexture)
10856 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10858 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10860 case TEXTURELAYERTYPE_TEXTURE:
10861 // singletexture unlit texture with transparency support
10862 R_Mesh_TexBind(0, layer->texture);
10863 R_Mesh_TexMatrix(0, &layer->texmatrix);
10864 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10865 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10866 R_Mesh_TexBind(1, 0);
10867 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10868 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10870 case TEXTURELAYERTYPE_FOG:
10871 // singletexture fogging
10872 if (layer->texture)
10874 R_Mesh_TexBind(0, layer->texture);
10875 R_Mesh_TexMatrix(0, &layer->texmatrix);
10876 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10877 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10881 R_Mesh_TexBind(0, 0);
10882 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10884 R_Mesh_TexBind(1, 0);
10885 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10886 // generate a color array for the fog pass
10887 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10888 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10892 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10895 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10897 GL_DepthFunc(GL_LEQUAL);
10898 GL_AlphaTest(false);
10902 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10904 // OpenGL 1.1 - crusty old voodoo path
10907 const texturelayer_t *layer;
10908 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);
10909 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10911 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10913 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10915 if (layerindex == 0)
10916 GL_AlphaTest(true);
10919 GL_AlphaTest(false);
10920 GL_DepthFunc(GL_EQUAL);
10923 GL_DepthMask(layer->depthmask && writedepth);
10924 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10925 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10926 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10927 switch (layer->type)
10929 case TEXTURELAYERTYPE_LITTEXTURE:
10930 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10932 // two-pass lit texture with 2x rgbscale
10933 // first the lightmap pass
10934 R_Mesh_TexBind(0, r_texture_white);
10935 R_Mesh_TexMatrix(0, NULL);
10936 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10937 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10938 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10939 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10940 else if (FAKELIGHT_ENABLED)
10941 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10942 else if (rsurface.uselightmaptexture)
10943 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10945 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10946 // then apply the texture to it
10947 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10948 R_Mesh_TexBind(0, layer->texture);
10949 R_Mesh_TexMatrix(0, &layer->texmatrix);
10950 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10951 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10952 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);
10956 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10957 R_Mesh_TexBind(0, layer->texture);
10958 R_Mesh_TexMatrix(0, &layer->texmatrix);
10959 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10960 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10961 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10962 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);
10963 else if (FAKELIGHT_ENABLED)
10964 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);
10966 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);
10969 case TEXTURELAYERTYPE_TEXTURE:
10970 // singletexture unlit texture with transparency support
10971 R_Mesh_TexBind(0, layer->texture);
10972 R_Mesh_TexMatrix(0, &layer->texmatrix);
10973 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10974 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10975 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);
10977 case TEXTURELAYERTYPE_FOG:
10978 // singletexture fogging
10979 if (layer->texture)
10981 R_Mesh_TexBind(0, layer->texture);
10982 R_Mesh_TexMatrix(0, &layer->texmatrix);
10983 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10984 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10988 R_Mesh_TexBind(0, 0);
10989 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10991 // generate a color array for the fog pass
10992 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10993 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10997 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11000 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11002 GL_DepthFunc(GL_LEQUAL);
11003 GL_AlphaTest(false);
11007 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11011 r_vertexgeneric_t *batchvertex;
11014 // R_Mesh_ResetTextureState();
11015 R_SetupShader_Generic_NoTexture(false, false);
11017 if(rsurface.texture && rsurface.texture->currentskinframe)
11019 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
11020 c[3] *= rsurface.texture->currentalpha;
11030 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
11032 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
11033 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
11034 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
11037 // brighten it up (as texture value 127 means "unlit")
11038 c[0] *= 2 * r_refdef.view.colorscale;
11039 c[1] *= 2 * r_refdef.view.colorscale;
11040 c[2] *= 2 * r_refdef.view.colorscale;
11042 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11043 c[3] *= r_wateralpha.value;
11045 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11047 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11048 GL_DepthMask(false);
11050 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11052 GL_BlendFunc(GL_ONE, GL_ONE);
11053 GL_DepthMask(false);
11055 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11057 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11058 GL_DepthMask(false);
11060 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11062 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11063 GL_DepthMask(false);
11067 GL_BlendFunc(GL_ONE, GL_ZERO);
11068 GL_DepthMask(writedepth);
11071 if (r_showsurfaces.integer == 3)
11073 rsurface.passcolor4f = NULL;
11075 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11077 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11079 rsurface.passcolor4f = NULL;
11080 rsurface.passcolor4f_vertexbuffer = 0;
11081 rsurface.passcolor4f_bufferoffset = 0;
11083 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11085 qboolean applycolor = true;
11088 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11090 r_refdef.lightmapintensity = 1;
11091 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
11092 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11094 else if (FAKELIGHT_ENABLED)
11096 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11098 r_refdef.lightmapintensity = r_fakelight_intensity.value;
11099 RSurf_DrawBatch_GL11_ApplyFakeLight();
11100 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11104 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11106 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11107 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11108 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11111 if(!rsurface.passcolor4f)
11112 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11114 RSurf_DrawBatch_GL11_ApplyAmbient();
11115 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11116 if(r_refdef.fogenabled)
11117 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11118 RSurf_DrawBatch_GL11_ClampColor();
11120 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11121 R_SetupShader_Generic_NoTexture(false, false);
11124 else if (!r_refdef.view.showdebug)
11126 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11127 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11128 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11130 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11131 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11133 R_Mesh_PrepareVertices_Generic_Unlock();
11136 else if (r_showsurfaces.integer == 4)
11138 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11139 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11140 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11142 unsigned char c = (vi << 3) * (1.0f / 256.0f);
11143 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11144 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
11146 R_Mesh_PrepareVertices_Generic_Unlock();
11149 else if (r_showsurfaces.integer == 2)
11152 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11153 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11154 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11156 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11157 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11158 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11159 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11160 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
11161 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
11162 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
11164 R_Mesh_PrepareVertices_Generic_Unlock();
11165 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11169 int texturesurfaceindex;
11171 const msurface_t *surface;
11172 float surfacecolor4f[4];
11173 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11174 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11176 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11178 surface = texturesurfacelist[texturesurfaceindex];
11179 k = (int)(((size_t)surface) / sizeof(msurface_t));
11180 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11181 for (j = 0;j < surface->num_vertices;j++)
11183 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11184 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11188 R_Mesh_PrepareVertices_Generic_Unlock();
11193 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11196 RSurf_SetupDepthAndCulling();
11197 if (r_showsurfaces.integer)
11199 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11202 switch (vid.renderpath)
11204 case RENDERPATH_GL20:
11205 case RENDERPATH_D3D9:
11206 case RENDERPATH_D3D10:
11207 case RENDERPATH_D3D11:
11208 case RENDERPATH_SOFT:
11209 case RENDERPATH_GLES2:
11210 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11212 case RENDERPATH_GL13:
11213 case RENDERPATH_GLES1:
11214 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11216 case RENDERPATH_GL11:
11217 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11223 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11226 RSurf_SetupDepthAndCulling();
11227 if (r_showsurfaces.integer)
11229 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11232 switch (vid.renderpath)
11234 case RENDERPATH_GL20:
11235 case RENDERPATH_D3D9:
11236 case RENDERPATH_D3D10:
11237 case RENDERPATH_D3D11:
11238 case RENDERPATH_SOFT:
11239 case RENDERPATH_GLES2:
11240 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11242 case RENDERPATH_GL13:
11243 case RENDERPATH_GLES1:
11244 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11246 case RENDERPATH_GL11:
11247 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11253 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11256 int texturenumsurfaces, endsurface;
11257 texture_t *texture;
11258 const msurface_t *surface;
11259 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11261 // if the model is static it doesn't matter what value we give for
11262 // wantnormals and wanttangents, so this logic uses only rules applicable
11263 // to a model, knowing that they are meaningless otherwise
11264 if (ent == r_refdef.scene.worldentity)
11265 RSurf_ActiveWorldEntity();
11266 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11267 RSurf_ActiveModelEntity(ent, false, false, false);
11270 switch (vid.renderpath)
11272 case RENDERPATH_GL20:
11273 case RENDERPATH_D3D9:
11274 case RENDERPATH_D3D10:
11275 case RENDERPATH_D3D11:
11276 case RENDERPATH_SOFT:
11277 case RENDERPATH_GLES2:
11278 RSurf_ActiveModelEntity(ent, true, true, false);
11280 case RENDERPATH_GL11:
11281 case RENDERPATH_GL13:
11282 case RENDERPATH_GLES1:
11283 RSurf_ActiveModelEntity(ent, true, false, false);
11288 if (r_transparentdepthmasking.integer)
11290 qboolean setup = false;
11291 for (i = 0;i < numsurfaces;i = j)
11294 surface = rsurface.modelsurfaces + surfacelist[i];
11295 texture = surface->texture;
11296 rsurface.texture = R_GetCurrentTexture(texture);
11297 rsurface.lightmaptexture = NULL;
11298 rsurface.deluxemaptexture = NULL;
11299 rsurface.uselightmaptexture = false;
11300 // scan ahead until we find a different texture
11301 endsurface = min(i + 1024, numsurfaces);
11302 texturenumsurfaces = 0;
11303 texturesurfacelist[texturenumsurfaces++] = surface;
11304 for (;j < endsurface;j++)
11306 surface = rsurface.modelsurfaces + surfacelist[j];
11307 if (texture != surface->texture)
11309 texturesurfacelist[texturenumsurfaces++] = surface;
11311 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11313 // render the range of surfaces as depth
11317 GL_ColorMask(0,0,0,0);
11319 GL_DepthTest(true);
11320 GL_BlendFunc(GL_ONE, GL_ZERO);
11321 GL_DepthMask(true);
11322 // R_Mesh_ResetTextureState();
11324 RSurf_SetupDepthAndCulling();
11325 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11326 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11327 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11331 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11334 for (i = 0;i < numsurfaces;i = j)
11337 surface = rsurface.modelsurfaces + surfacelist[i];
11338 texture = surface->texture;
11339 rsurface.texture = R_GetCurrentTexture(texture);
11340 // scan ahead until we find a different texture
11341 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11342 texturenumsurfaces = 0;
11343 texturesurfacelist[texturenumsurfaces++] = surface;
11344 if(FAKELIGHT_ENABLED)
11346 rsurface.lightmaptexture = NULL;
11347 rsurface.deluxemaptexture = NULL;
11348 rsurface.uselightmaptexture = false;
11349 for (;j < endsurface;j++)
11351 surface = rsurface.modelsurfaces + surfacelist[j];
11352 if (texture != surface->texture)
11354 texturesurfacelist[texturenumsurfaces++] = surface;
11359 rsurface.lightmaptexture = surface->lightmaptexture;
11360 rsurface.deluxemaptexture = surface->deluxemaptexture;
11361 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11362 for (;j < endsurface;j++)
11364 surface = rsurface.modelsurfaces + surfacelist[j];
11365 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11367 texturesurfacelist[texturenumsurfaces++] = surface;
11370 // render the range of surfaces
11371 if (ent == r_refdef.scene.worldentity)
11372 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11374 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11376 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11379 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11381 // transparent surfaces get pushed off into the transparent queue
11382 int surfacelistindex;
11383 const msurface_t *surface;
11384 vec3_t tempcenter, center;
11385 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11387 surface = texturesurfacelist[surfacelistindex];
11388 if (r_transparent_sortsurfacesbynearest.integer)
11390 tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11391 tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11392 tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11396 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11397 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11398 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11400 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11401 if (rsurface.entity->transparent_offset) // transparent offset
11403 center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11404 center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11405 center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11407 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);
11411 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11413 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11415 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11417 RSurf_SetupDepthAndCulling();
11418 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11419 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11420 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11424 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11428 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11431 if (!rsurface.texture->currentnumlayers)
11433 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11434 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11436 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11438 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11439 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11440 else if (!rsurface.texture->currentnumlayers)
11442 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11444 // in the deferred case, transparent surfaces were queued during prepass
11445 if (!r_shadow_usingdeferredprepass)
11446 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11450 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11451 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11456 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11459 texture_t *texture;
11460 R_FrameData_SetMark();
11461 // break the surface list down into batches by texture and use of lightmapping
11462 for (i = 0;i < numsurfaces;i = j)
11465 // texture is the base texture pointer, rsurface.texture is the
11466 // current frame/skin the texture is directing us to use (for example
11467 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11468 // use skin 1 instead)
11469 texture = surfacelist[i]->texture;
11470 rsurface.texture = R_GetCurrentTexture(texture);
11471 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11473 // if this texture is not the kind we want, skip ahead to the next one
11474 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11478 if(FAKELIGHT_ENABLED || depthonly || prepass)
11480 rsurface.lightmaptexture = NULL;
11481 rsurface.deluxemaptexture = NULL;
11482 rsurface.uselightmaptexture = false;
11483 // simply scan ahead until we find a different texture or lightmap state
11484 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11489 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11490 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11491 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11492 // simply scan ahead until we find a different texture or lightmap state
11493 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11496 // render the range of surfaces
11497 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11499 R_FrameData_ReturnToMark();
11502 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11506 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11509 if (!rsurface.texture->currentnumlayers)
11511 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11512 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11514 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11516 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11517 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11518 else if (!rsurface.texture->currentnumlayers)
11520 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11522 // in the deferred case, transparent surfaces were queued during prepass
11523 if (!r_shadow_usingdeferredprepass)
11524 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11528 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11529 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11534 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11537 texture_t *texture;
11538 R_FrameData_SetMark();
11539 // break the surface list down into batches by texture and use of lightmapping
11540 for (i = 0;i < numsurfaces;i = j)
11543 // texture is the base texture pointer, rsurface.texture is the
11544 // current frame/skin the texture is directing us to use (for example
11545 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11546 // use skin 1 instead)
11547 texture = surfacelist[i]->texture;
11548 rsurface.texture = R_GetCurrentTexture(texture);
11549 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11551 // if this texture is not the kind we want, skip ahead to the next one
11552 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11556 if(FAKELIGHT_ENABLED || depthonly || prepass)
11558 rsurface.lightmaptexture = NULL;
11559 rsurface.deluxemaptexture = NULL;
11560 rsurface.uselightmaptexture = false;
11561 // simply scan ahead until we find a different texture or lightmap state
11562 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11567 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11568 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11569 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11570 // simply scan ahead until we find a different texture or lightmap state
11571 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11574 // render the range of surfaces
11575 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11577 R_FrameData_ReturnToMark();
11580 float locboxvertex3f[6*4*3] =
11582 1,0,1, 1,0,0, 1,1,0, 1,1,1,
11583 0,1,1, 0,1,0, 0,0,0, 0,0,1,
11584 1,1,1, 1,1,0, 0,1,0, 0,1,1,
11585 0,0,1, 0,0,0, 1,0,0, 1,0,1,
11586 0,0,1, 1,0,1, 1,1,1, 0,1,1,
11587 1,0,0, 0,0,0, 0,1,0, 1,1,0
11590 unsigned short locboxelements[6*2*3] =
11595 12,13,14, 12,14,15,
11596 16,17,18, 16,18,19,
11600 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11603 cl_locnode_t *loc = (cl_locnode_t *)ent;
11605 float vertex3f[6*4*3];
11607 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11608 GL_DepthMask(false);
11609 GL_DepthRange(0, 1);
11610 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11611 GL_DepthTest(true);
11612 GL_CullFace(GL_NONE);
11613 R_EntityMatrix(&identitymatrix);
11615 // R_Mesh_ResetTextureState();
11617 i = surfacelist[0];
11618 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11619 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11620 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11621 surfacelist[0] < 0 ? 0.5f : 0.125f);
11623 if (VectorCompare(loc->mins, loc->maxs))
11625 VectorSet(size, 2, 2, 2);
11626 VectorMA(loc->mins, -0.5f, size, mins);
11630 VectorCopy(loc->mins, mins);
11631 VectorSubtract(loc->maxs, loc->mins, size);
11634 for (i = 0;i < 6*4*3;)
11635 for (j = 0;j < 3;j++, i++)
11636 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11638 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11639 R_SetupShader_Generic_NoTexture(false, false);
11640 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11643 void R_DrawLocs(void)
11646 cl_locnode_t *loc, *nearestloc;
11648 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11649 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11651 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11652 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11656 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11658 if (decalsystem->decals)
11659 Mem_Free(decalsystem->decals);
11660 memset(decalsystem, 0, sizeof(*decalsystem));
11663 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)
11666 tridecal_t *decals;
11669 // expand or initialize the system
11670 if (decalsystem->maxdecals <= decalsystem->numdecals)
11672 decalsystem_t old = *decalsystem;
11673 qboolean useshortelements;
11674 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11675 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11676 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)));
11677 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11678 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11679 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11680 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11681 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11682 if (decalsystem->numdecals)
11683 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11685 Mem_Free(old.decals);
11686 for (i = 0;i < decalsystem->maxdecals*3;i++)
11687 decalsystem->element3i[i] = i;
11688 if (useshortelements)
11689 for (i = 0;i < decalsystem->maxdecals*3;i++)
11690 decalsystem->element3s[i] = i;
11693 // grab a decal and search for another free slot for the next one
11694 decals = decalsystem->decals;
11695 decal = decalsystem->decals + (i = decalsystem->freedecal++);
11696 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11698 decalsystem->freedecal = i;
11699 if (decalsystem->numdecals <= i)
11700 decalsystem->numdecals = i + 1;
11702 // initialize the decal
11704 decal->triangleindex = triangleindex;
11705 decal->surfaceindex = surfaceindex;
11706 decal->decalsequence = decalsequence;
11707 decal->color4f[0][0] = c0[0];
11708 decal->color4f[0][1] = c0[1];
11709 decal->color4f[0][2] = c0[2];
11710 decal->color4f[0][3] = 1;
11711 decal->color4f[1][0] = c1[0];
11712 decal->color4f[1][1] = c1[1];
11713 decal->color4f[1][2] = c1[2];
11714 decal->color4f[1][3] = 1;
11715 decal->color4f[2][0] = c2[0];
11716 decal->color4f[2][1] = c2[1];
11717 decal->color4f[2][2] = c2[2];
11718 decal->color4f[2][3] = 1;
11719 decal->vertex3f[0][0] = v0[0];
11720 decal->vertex3f[0][1] = v0[1];
11721 decal->vertex3f[0][2] = v0[2];
11722 decal->vertex3f[1][0] = v1[0];
11723 decal->vertex3f[1][1] = v1[1];
11724 decal->vertex3f[1][2] = v1[2];
11725 decal->vertex3f[2][0] = v2[0];
11726 decal->vertex3f[2][1] = v2[1];
11727 decal->vertex3f[2][2] = v2[2];
11728 decal->texcoord2f[0][0] = t0[0];
11729 decal->texcoord2f[0][1] = t0[1];
11730 decal->texcoord2f[1][0] = t1[0];
11731 decal->texcoord2f[1][1] = t1[1];
11732 decal->texcoord2f[2][0] = t2[0];
11733 decal->texcoord2f[2][1] = t2[1];
11734 TriangleNormal(v0, v1, v2, decal->plane);
11735 VectorNormalize(decal->plane);
11736 decal->plane[3] = DotProduct(v0, decal->plane);
11739 extern cvar_t cl_decals_bias;
11740 extern cvar_t cl_decals_models;
11741 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11742 // baseparms, parms, temps
11743 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)
11748 const float *vertex3f;
11749 const float *normal3f;
11751 float points[2][9][3];
11758 e = rsurface.modelelement3i + 3*triangleindex;
11760 vertex3f = rsurface.modelvertex3f;
11761 normal3f = rsurface.modelnormal3f;
11765 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11767 index = 3*e[cornerindex];
11768 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11773 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11775 index = 3*e[cornerindex];
11776 VectorCopy(vertex3f + index, v[cornerindex]);
11781 //TriangleNormal(v[0], v[1], v[2], normal);
11782 //if (DotProduct(normal, localnormal) < 0.0f)
11784 // clip by each of the box planes formed from the projection matrix
11785 // if anything survives, we emit the decal
11786 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]);
11789 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]);
11792 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]);
11795 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]);
11798 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]);
11801 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]);
11804 // some part of the triangle survived, so we have to accept it...
11807 // dynamic always uses the original triangle
11809 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11811 index = 3*e[cornerindex];
11812 VectorCopy(vertex3f + index, v[cornerindex]);
11815 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11817 // convert vertex positions to texcoords
11818 Matrix4x4_Transform(projection, v[cornerindex], temp);
11819 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11820 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11821 // calculate distance fade from the projection origin
11822 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11823 f = bound(0.0f, f, 1.0f);
11824 c[cornerindex][0] = r * f;
11825 c[cornerindex][1] = g * f;
11826 c[cornerindex][2] = b * f;
11827 c[cornerindex][3] = 1.0f;
11828 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11831 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);
11833 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11834 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);
11836 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)
11838 matrix4x4_t projection;
11839 decalsystem_t *decalsystem;
11842 const msurface_t *surface;
11843 const msurface_t *surfaces;
11844 const int *surfacelist;
11845 const texture_t *texture;
11847 int numsurfacelist;
11848 int surfacelistindex;
11851 float localorigin[3];
11852 float localnormal[3];
11853 float localmins[3];
11854 float localmaxs[3];
11857 float planes[6][4];
11860 int bih_triangles_count;
11861 int bih_triangles[256];
11862 int bih_surfaces[256];
11864 decalsystem = &ent->decalsystem;
11865 model = ent->model;
11866 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11868 R_DecalSystem_Reset(&ent->decalsystem);
11872 if (!model->brush.data_leafs && !cl_decals_models.integer)
11874 if (decalsystem->model)
11875 R_DecalSystem_Reset(decalsystem);
11879 if (decalsystem->model != model)
11880 R_DecalSystem_Reset(decalsystem);
11881 decalsystem->model = model;
11883 RSurf_ActiveModelEntity(ent, true, false, false);
11885 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11886 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11887 VectorNormalize(localnormal);
11888 localsize = worldsize*rsurface.inversematrixscale;
11889 localmins[0] = localorigin[0] - localsize;
11890 localmins[1] = localorigin[1] - localsize;
11891 localmins[2] = localorigin[2] - localsize;
11892 localmaxs[0] = localorigin[0] + localsize;
11893 localmaxs[1] = localorigin[1] + localsize;
11894 localmaxs[2] = localorigin[2] + localsize;
11896 //VectorCopy(localnormal, planes[4]);
11897 //VectorVectors(planes[4], planes[2], planes[0]);
11898 AnglesFromVectors(angles, localnormal, NULL, false);
11899 AngleVectors(angles, planes[0], planes[2], planes[4]);
11900 VectorNegate(planes[0], planes[1]);
11901 VectorNegate(planes[2], planes[3]);
11902 VectorNegate(planes[4], planes[5]);
11903 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11904 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11905 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11906 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11907 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11908 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11913 matrix4x4_t forwardprojection;
11914 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11915 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11920 float projectionvector[4][3];
11921 VectorScale(planes[0], ilocalsize, projectionvector[0]);
11922 VectorScale(planes[2], ilocalsize, projectionvector[1]);
11923 VectorScale(planes[4], ilocalsize, projectionvector[2]);
11924 projectionvector[0][0] = planes[0][0] * ilocalsize;
11925 projectionvector[0][1] = planes[1][0] * ilocalsize;
11926 projectionvector[0][2] = planes[2][0] * ilocalsize;
11927 projectionvector[1][0] = planes[0][1] * ilocalsize;
11928 projectionvector[1][1] = planes[1][1] * ilocalsize;
11929 projectionvector[1][2] = planes[2][1] * ilocalsize;
11930 projectionvector[2][0] = planes[0][2] * ilocalsize;
11931 projectionvector[2][1] = planes[1][2] * ilocalsize;
11932 projectionvector[2][2] = planes[2][2] * ilocalsize;
11933 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11934 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11935 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11936 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11940 dynamic = model->surfmesh.isanimated;
11941 numsurfacelist = model->nummodelsurfaces;
11942 surfacelist = model->sortedmodelsurfaces;
11943 surfaces = model->data_surfaces;
11946 bih_triangles_count = -1;
11949 if(model->render_bih.numleafs)
11950 bih = &model->render_bih;
11951 else if(model->collision_bih.numleafs)
11952 bih = &model->collision_bih;
11955 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11956 if(bih_triangles_count == 0)
11958 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11960 if(bih_triangles_count > 0)
11962 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11964 surfaceindex = bih_surfaces[triangleindex];
11965 surface = surfaces + surfaceindex;
11966 texture = surface->texture;
11967 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11969 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11971 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11976 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11978 surfaceindex = surfacelist[surfacelistindex];
11979 surface = surfaces + surfaceindex;
11980 // check cull box first because it rejects more than any other check
11981 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11983 // skip transparent surfaces
11984 texture = surface->texture;
11985 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11987 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11989 numtriangles = surface->num_triangles;
11990 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11991 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11996 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11997 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)
11999 int renderentityindex;
12000 float worldmins[3];
12001 float worldmaxs[3];
12002 entity_render_t *ent;
12004 if (!cl_decals_newsystem.integer)
12007 worldmins[0] = worldorigin[0] - worldsize;
12008 worldmins[1] = worldorigin[1] - worldsize;
12009 worldmins[2] = worldorigin[2] - worldsize;
12010 worldmaxs[0] = worldorigin[0] + worldsize;
12011 worldmaxs[1] = worldorigin[1] + worldsize;
12012 worldmaxs[2] = worldorigin[2] + worldsize;
12014 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12016 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
12018 ent = r_refdef.scene.entities[renderentityindex];
12019 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
12022 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12026 typedef struct r_decalsystem_splatqueue_s
12028 vec3_t worldorigin;
12029 vec3_t worldnormal;
12033 unsigned int decalsequence;
12035 r_decalsystem_splatqueue_t;
12037 int r_decalsystem_numqueued = 0;
12038 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
12040 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)
12042 r_decalsystem_splatqueue_t *queue;
12044 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
12047 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
12048 VectorCopy(worldorigin, queue->worldorigin);
12049 VectorCopy(worldnormal, queue->worldnormal);
12050 Vector4Set(queue->color, r, g, b, a);
12051 Vector4Set(queue->tcrange, s1, t1, s2, t2);
12052 queue->worldsize = worldsize;
12053 queue->decalsequence = cl.decalsequence++;
12056 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
12059 r_decalsystem_splatqueue_t *queue;
12061 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
12062 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);
12063 r_decalsystem_numqueued = 0;
12066 extern cvar_t cl_decals_max;
12067 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12070 decalsystem_t *decalsystem = &ent->decalsystem;
12072 unsigned int killsequence;
12077 if (!decalsystem->numdecals)
12080 if (r_showsurfaces.integer)
12083 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12085 R_DecalSystem_Reset(decalsystem);
12089 killsequence = cl.decalsequence - bound(1, (unsigned int) cl_decals_max.integer, cl.decalsequence);
12090 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12092 if (decalsystem->lastupdatetime)
12093 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
12096 decalsystem->lastupdatetime = r_refdef.scene.time;
12097 numdecals = decalsystem->numdecals;
12099 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12101 if (decal->color4f[0][3])
12103 decal->lived += frametime;
12104 if (killsequence > decal->decalsequence || decal->lived >= lifetime)
12106 memset(decal, 0, sizeof(*decal));
12107 if (decalsystem->freedecal > i)
12108 decalsystem->freedecal = i;
12112 decal = decalsystem->decals;
12113 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
12116 // collapse the array by shuffling the tail decals into the gaps
12119 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
12120 decalsystem->freedecal++;
12121 if (decalsystem->freedecal == numdecals)
12123 decal[decalsystem->freedecal] = decal[--numdecals];
12126 decalsystem->numdecals = numdecals;
12128 if (numdecals <= 0)
12130 // if there are no decals left, reset decalsystem
12131 R_DecalSystem_Reset(decalsystem);
12135 extern skinframe_t *decalskinframe;
12136 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12139 decalsystem_t *decalsystem = &ent->decalsystem;
12148 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12151 numdecals = decalsystem->numdecals;
12155 if (r_showsurfaces.integer)
12158 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12160 R_DecalSystem_Reset(decalsystem);
12164 // if the model is static it doesn't matter what value we give for
12165 // wantnormals and wanttangents, so this logic uses only rules applicable
12166 // to a model, knowing that they are meaningless otherwise
12167 if (ent == r_refdef.scene.worldentity)
12168 RSurf_ActiveWorldEntity();
12170 RSurf_ActiveModelEntity(ent, false, false, false);
12172 decalsystem->lastupdatetime = r_refdef.scene.time;
12174 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12176 // update vertex positions for animated models
12177 v3f = decalsystem->vertex3f;
12178 c4f = decalsystem->color4f;
12179 t2f = decalsystem->texcoord2f;
12180 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12182 if (!decal->color4f[0][3])
12185 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12189 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
12192 // update color values for fading decals
12193 if (decal->lived >= cl_decals_time.value)
12194 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12198 c4f[ 0] = decal->color4f[0][0] * alpha;
12199 c4f[ 1] = decal->color4f[0][1] * alpha;
12200 c4f[ 2] = decal->color4f[0][2] * alpha;
12202 c4f[ 4] = decal->color4f[1][0] * alpha;
12203 c4f[ 5] = decal->color4f[1][1] * alpha;
12204 c4f[ 6] = decal->color4f[1][2] * alpha;
12206 c4f[ 8] = decal->color4f[2][0] * alpha;
12207 c4f[ 9] = decal->color4f[2][1] * alpha;
12208 c4f[10] = decal->color4f[2][2] * alpha;
12211 t2f[0] = decal->texcoord2f[0][0];
12212 t2f[1] = decal->texcoord2f[0][1];
12213 t2f[2] = decal->texcoord2f[1][0];
12214 t2f[3] = decal->texcoord2f[1][1];
12215 t2f[4] = decal->texcoord2f[2][0];
12216 t2f[5] = decal->texcoord2f[2][1];
12218 // update vertex positions for animated models
12219 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12221 e = rsurface.modelelement3i + 3*decal->triangleindex;
12222 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12223 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12224 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12228 VectorCopy(decal->vertex3f[0], v3f);
12229 VectorCopy(decal->vertex3f[1], v3f + 3);
12230 VectorCopy(decal->vertex3f[2], v3f + 6);
12233 if (r_refdef.fogenabled)
12235 alpha = RSurf_FogVertex(v3f);
12236 VectorScale(c4f, alpha, c4f);
12237 alpha = RSurf_FogVertex(v3f + 3);
12238 VectorScale(c4f + 4, alpha, c4f + 4);
12239 alpha = RSurf_FogVertex(v3f + 6);
12240 VectorScale(c4f + 8, alpha, c4f + 8);
12251 r_refdef.stats[r_stat_drawndecals] += numtris;
12253 // now render the decals all at once
12254 // (this assumes they all use one particle font texture!)
12255 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);
12256 // R_Mesh_ResetTextureState();
12257 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12258 GL_DepthMask(false);
12259 GL_DepthRange(0, 1);
12260 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12261 GL_DepthTest(true);
12262 GL_CullFace(GL_NONE);
12263 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12264 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12265 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12269 static void R_DrawModelDecals(void)
12273 // fade faster when there are too many decals
12274 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12275 for (i = 0;i < r_refdef.scene.numentities;i++)
12276 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12278 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12279 for (i = 0;i < r_refdef.scene.numentities;i++)
12280 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12281 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12283 R_DecalSystem_ApplySplatEntitiesQueue();
12285 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12286 for (i = 0;i < r_refdef.scene.numentities;i++)
12287 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12289 r_refdef.stats[r_stat_totaldecals] += numdecals;
12291 if (r_showsurfaces.integer)
12294 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12296 for (i = 0;i < r_refdef.scene.numentities;i++)
12298 if (!r_refdef.viewcache.entityvisible[i])
12300 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12301 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12305 extern cvar_t mod_collision_bih;
12306 static void R_DrawDebugModel(void)
12308 entity_render_t *ent = rsurface.entity;
12309 int i, j, flagsmask;
12310 const msurface_t *surface;
12311 dp_model_t *model = ent->model;
12313 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12316 if (r_showoverdraw.value > 0)
12318 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12319 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12320 R_SetupShader_Generic_NoTexture(false, false);
12321 GL_DepthTest(false);
12322 GL_DepthMask(false);
12323 GL_DepthRange(0, 1);
12324 GL_BlendFunc(GL_ONE, GL_ONE);
12325 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12327 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12329 rsurface.texture = R_GetCurrentTexture(surface->texture);
12330 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12332 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12333 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12334 if (!rsurface.texture->currentlayers->depthmask)
12335 GL_Color(c, 0, 0, 1.0f);
12336 else if (ent == r_refdef.scene.worldentity)
12337 GL_Color(c, c, c, 1.0f);
12339 GL_Color(0, c, 0, 1.0f);
12340 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12344 rsurface.texture = NULL;
12347 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12349 // R_Mesh_ResetTextureState();
12350 R_SetupShader_Generic_NoTexture(false, false);
12351 GL_DepthRange(0, 1);
12352 GL_DepthTest(!r_showdisabledepthtest.integer);
12353 GL_DepthMask(false);
12354 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12356 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12360 qboolean cullbox = false;
12361 const q3mbrush_t *brush;
12362 const bih_t *bih = &model->collision_bih;
12363 const bih_leaf_t *bihleaf;
12364 float vertex3f[3][3];
12365 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12366 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12368 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12370 switch (bihleaf->type)
12373 brush = model->brush.data_brushes + bihleaf->itemindex;
12374 if (brush->colbrushf && brush->colbrushf->numtriangles)
12376 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);
12377 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12378 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12381 case BIH_COLLISIONTRIANGLE:
12382 triangleindex = bihleaf->itemindex;
12383 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12384 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12385 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12386 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);
12387 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12388 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12390 case BIH_RENDERTRIANGLE:
12391 triangleindex = bihleaf->itemindex;
12392 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12393 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12394 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12395 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);
12396 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12397 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12403 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12406 if (r_showtris.integer && qglPolygonMode)
12408 if (r_showdisabledepthtest.integer)
12410 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12411 GL_DepthMask(false);
12415 GL_BlendFunc(GL_ONE, GL_ZERO);
12416 GL_DepthMask(true);
12418 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12419 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12421 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12423 rsurface.texture = R_GetCurrentTexture(surface->texture);
12424 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12426 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12427 if (!rsurface.texture->currentlayers->depthmask)
12428 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12429 else if (ent == r_refdef.scene.worldentity)
12430 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12432 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12433 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12437 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12438 rsurface.texture = NULL;
12441 if (r_shownormals.value != 0 && qglBegin)
12445 if (r_showdisabledepthtest.integer)
12447 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12448 GL_DepthMask(false);
12452 GL_BlendFunc(GL_ONE, GL_ZERO);
12453 GL_DepthMask(true);
12455 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12457 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12459 rsurface.texture = R_GetCurrentTexture(surface->texture);
12460 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12462 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12463 qglBegin(GL_LINES);
12464 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12466 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12468 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12469 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12470 qglVertex3f(v[0], v[1], v[2]);
12471 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12472 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12473 qglVertex3f(v[0], v[1], v[2]);
12476 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12478 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12480 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12481 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12482 qglVertex3f(v[0], v[1], v[2]);
12483 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12484 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12485 qglVertex3f(v[0], v[1], v[2]);
12488 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12490 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12492 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12493 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12494 qglVertex3f(v[0], v[1], v[2]);
12495 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12496 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12497 qglVertex3f(v[0], v[1], v[2]);
12500 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12502 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12504 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12505 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12506 qglVertex3f(v[0], v[1], v[2]);
12507 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12508 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12509 qglVertex3f(v[0], v[1], v[2]);
12516 rsurface.texture = NULL;
12521 int r_maxsurfacelist = 0;
12522 const msurface_t **r_surfacelist = NULL;
12523 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12525 int i, j, endj, flagsmask;
12526 dp_model_t *model = r_refdef.scene.worldmodel;
12527 msurface_t *surfaces;
12528 unsigned char *update;
12529 int numsurfacelist = 0;
12533 if (r_maxsurfacelist < model->num_surfaces)
12535 r_maxsurfacelist = model->num_surfaces;
12537 Mem_Free((msurface_t**)r_surfacelist);
12538 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12541 RSurf_ActiveWorldEntity();
12543 surfaces = model->data_surfaces;
12544 update = model->brushq1.lightmapupdateflags;
12546 // update light styles on this submodel
12547 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12549 model_brush_lightstyleinfo_t *style;
12550 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12552 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12554 int *list = style->surfacelist;
12555 style->value = r_refdef.scene.lightstylevalue[style->style];
12556 for (j = 0;j < style->numsurfaces;j++)
12557 update[list[j]] = true;
12562 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12566 R_DrawDebugModel();
12567 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12571 rsurface.lightmaptexture = NULL;
12572 rsurface.deluxemaptexture = NULL;
12573 rsurface.uselightmaptexture = false;
12574 rsurface.texture = NULL;
12575 rsurface.rtlight = NULL;
12576 numsurfacelist = 0;
12577 // add visible surfaces to draw list
12578 for (i = 0;i < model->nummodelsurfaces;i++)
12580 j = model->sortedmodelsurfaces[i];
12581 if (r_refdef.viewcache.world_surfacevisible[j])
12582 r_surfacelist[numsurfacelist++] = surfaces + j;
12584 // update lightmaps if needed
12585 if (model->brushq1.firstrender)
12587 model->brushq1.firstrender = false;
12588 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12590 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12594 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12595 if (r_refdef.viewcache.world_surfacevisible[j])
12597 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12599 // don't do anything if there were no surfaces
12600 if (!numsurfacelist)
12602 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12605 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12607 // add to stats if desired
12608 if (r_speeds.integer && !skysurfaces && !depthonly)
12610 r_refdef.stats[r_stat_world_surfaces] += numsurfacelist;
12611 for (j = 0;j < numsurfacelist;j++)
12612 r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles;
12615 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12618 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12620 int i, j, endj, flagsmask;
12621 dp_model_t *model = ent->model;
12622 msurface_t *surfaces;
12623 unsigned char *update;
12624 int numsurfacelist = 0;
12628 if (r_maxsurfacelist < model->num_surfaces)
12630 r_maxsurfacelist = model->num_surfaces;
12632 Mem_Free((msurface_t **)r_surfacelist);
12633 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12636 // if the model is static it doesn't matter what value we give for
12637 // wantnormals and wanttangents, so this logic uses only rules applicable
12638 // to a model, knowing that they are meaningless otherwise
12639 if (ent == r_refdef.scene.worldentity)
12640 RSurf_ActiveWorldEntity();
12641 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12642 RSurf_ActiveModelEntity(ent, false, false, false);
12644 RSurf_ActiveModelEntity(ent, true, true, true);
12645 else if (depthonly)
12647 switch (vid.renderpath)
12649 case RENDERPATH_GL20:
12650 case RENDERPATH_D3D9:
12651 case RENDERPATH_D3D10:
12652 case RENDERPATH_D3D11:
12653 case RENDERPATH_SOFT:
12654 case RENDERPATH_GLES2:
12655 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12657 case RENDERPATH_GL11:
12658 case RENDERPATH_GL13:
12659 case RENDERPATH_GLES1:
12660 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12666 switch (vid.renderpath)
12668 case RENDERPATH_GL20:
12669 case RENDERPATH_D3D9:
12670 case RENDERPATH_D3D10:
12671 case RENDERPATH_D3D11:
12672 case RENDERPATH_SOFT:
12673 case RENDERPATH_GLES2:
12674 RSurf_ActiveModelEntity(ent, true, true, false);
12676 case RENDERPATH_GL11:
12677 case RENDERPATH_GL13:
12678 case RENDERPATH_GLES1:
12679 RSurf_ActiveModelEntity(ent, true, false, false);
12684 surfaces = model->data_surfaces;
12685 update = model->brushq1.lightmapupdateflags;
12687 // update light styles
12688 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12690 model_brush_lightstyleinfo_t *style;
12691 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12693 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12695 int *list = style->surfacelist;
12696 style->value = r_refdef.scene.lightstylevalue[style->style];
12697 for (j = 0;j < style->numsurfaces;j++)
12698 update[list[j]] = true;
12703 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12707 R_DrawDebugModel();
12708 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12712 rsurface.lightmaptexture = NULL;
12713 rsurface.deluxemaptexture = NULL;
12714 rsurface.uselightmaptexture = false;
12715 rsurface.texture = NULL;
12716 rsurface.rtlight = NULL;
12717 numsurfacelist = 0;
12718 // add visible surfaces to draw list
12719 for (i = 0;i < model->nummodelsurfaces;i++)
12720 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12721 // don't do anything if there were no surfaces
12722 if (!numsurfacelist)
12724 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12727 // update lightmaps if needed
12731 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12736 R_BuildLightMap(ent, surfaces + j);
12741 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12743 // add to stats if desired
12744 if (r_speeds.integer && !skysurfaces && !depthonly)
12746 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12747 for (j = 0;j < numsurfacelist;j++)
12748 r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12751 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12754 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12756 static texture_t texture;
12757 static msurface_t surface;
12758 const msurface_t *surfacelist = &surface;
12760 // fake enough texture and surface state to render this geometry
12762 texture.update_lastrenderframe = -1; // regenerate this texture
12763 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12764 texture.basealpha = 1.0f;
12765 texture.currentskinframe = skinframe;
12766 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12767 texture.offsetmapping = OFFSETMAPPING_OFF;
12768 texture.offsetscale = 1;
12769 texture.specularscalemod = 1;
12770 texture.specularpowermod = 1;
12771 texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12772 // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12773 // JUST GREP FOR "specularscalemod = 1".
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);
12789 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)
12791 static msurface_t surface;
12792 const msurface_t *surfacelist = &surface;
12794 // fake enough texture and surface state to render this geometry
12795 surface.texture = texture;
12796 surface.num_triangles = numtriangles;
12797 surface.num_firsttriangle = firsttriangle;
12798 surface.num_vertices = numvertices;
12799 surface.num_firstvertex = firstvertex;
12802 rsurface.texture = R_GetCurrentTexture(surface.texture);
12803 rsurface.lightmaptexture = NULL;
12804 rsurface.deluxemaptexture = NULL;
12805 rsurface.uselightmaptexture = false;
12806 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);