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_prepass_width;
2147 extern int r_shadow_prepass_height;
2148 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2149 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2150 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2151 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2153 #define BLENDFUNC_ALLOWS_COLORMOD 1
2154 #define BLENDFUNC_ALLOWS_FOG 2
2155 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2156 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2157 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2158 static int R_BlendFuncFlags(int src, int dst)
2162 // a blendfunc allows colormod if:
2163 // a) it can never keep the destination pixel invariant, or
2164 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2165 // this is to prevent unintended side effects from colormod
2167 // a blendfunc allows fog if:
2168 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2169 // this is to prevent unintended side effects from fog
2171 // these checks are the output of fogeval.pl
2173 r |= BLENDFUNC_ALLOWS_COLORMOD;
2174 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2175 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2176 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2177 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2178 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2179 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2180 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2181 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2182 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2183 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2184 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2185 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2186 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2187 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2188 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2189 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2190 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2191 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2192 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2193 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2194 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2199 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)
2201 // select a permutation of the lighting shader appropriate to this
2202 // combination of texture, entity, light source, and fogging, only use the
2203 // minimum features necessary to avoid wasting rendering time in the
2204 // fragment shader on features that are not being used
2205 unsigned int permutation = 0;
2206 unsigned int mode = 0;
2208 static float dummy_colormod[3] = {1, 1, 1};
2209 float *colormod = rsurface.colormod;
2211 matrix4x4_t tempmatrix;
2212 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2213 if (r_trippy.integer && !notrippy)
2214 permutation |= SHADERPERMUTATION_TRIPPY;
2215 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2216 permutation |= SHADERPERMUTATION_ALPHAKILL;
2217 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_OCCLUDE)
2218 permutation |= SHADERPERMUTATION_OCCLUDE;
2219 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2220 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2221 if (rsurfacepass == RSURFPASS_BACKGROUND)
2223 // distorted background
2224 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2226 mode = SHADERMODE_WATER;
2227 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2228 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2229 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2231 // this is the right thing to do for wateralpha
2232 GL_BlendFunc(GL_ONE, GL_ZERO);
2233 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2237 // this is the right thing to do for entity alpha
2238 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2239 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2242 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2244 mode = SHADERMODE_REFRACTION;
2245 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2246 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2247 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2248 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2252 mode = SHADERMODE_GENERIC;
2253 permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2254 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2255 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2257 if (vid.allowalphatocoverage)
2258 GL_AlphaToCoverage(false);
2260 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2262 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2264 switch(rsurface.texture->offsetmapping)
2266 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2267 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2268 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2269 case OFFSETMAPPING_OFF: break;
2272 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2273 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2274 // normalmap (deferred prepass), may use alpha test on diffuse
2275 mode = SHADERMODE_DEFERREDGEOMETRY;
2276 GL_BlendFunc(GL_ONE, GL_ZERO);
2277 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2278 if (vid.allowalphatocoverage)
2279 GL_AlphaToCoverage(false);
2281 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2283 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2285 switch(rsurface.texture->offsetmapping)
2287 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2288 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2289 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2290 case OFFSETMAPPING_OFF: break;
2293 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2294 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2295 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2296 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2298 mode = SHADERMODE_LIGHTSOURCE;
2299 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2300 permutation |= SHADERPERMUTATION_CUBEFILTER;
2301 if (diffusescale > 0)
2302 permutation |= SHADERPERMUTATION_DIFFUSE;
2303 if (specularscale > 0)
2304 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2305 if (r_refdef.fogenabled)
2306 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2307 if (rsurface.texture->colormapping)
2308 permutation |= SHADERPERMUTATION_COLORMAPPING;
2309 if (r_shadow_usingshadowmap2d)
2311 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2312 if(r_shadow_shadowmapvsdct)
2313 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2315 if (r_shadow_shadowmap2ddepthbuffer)
2316 permutation |= SHADERPERMUTATION_DEPTHRGB;
2318 if (rsurface.texture->reflectmasktexture)
2319 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2320 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2321 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2322 if (vid.allowalphatocoverage)
2323 GL_AlphaToCoverage(false);
2325 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2327 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2329 switch(rsurface.texture->offsetmapping)
2331 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2332 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2333 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2334 case OFFSETMAPPING_OFF: break;
2337 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2338 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2339 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2340 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2341 // unshaded geometry (fullbright or ambient model lighting)
2342 mode = SHADERMODE_FLATCOLOR;
2343 ambientscale = diffusescale = specularscale = 0;
2344 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2345 permutation |= SHADERPERMUTATION_GLOW;
2346 if (r_refdef.fogenabled)
2347 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2348 if (rsurface.texture->colormapping)
2349 permutation |= SHADERPERMUTATION_COLORMAPPING;
2350 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2352 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2353 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2355 if (r_shadow_shadowmap2ddepthbuffer)
2356 permutation |= SHADERPERMUTATION_DEPTHRGB;
2358 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2359 permutation |= SHADERPERMUTATION_REFLECTION;
2360 if (rsurface.texture->reflectmasktexture)
2361 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2362 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2363 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2364 // when using alphatocoverage, we don't need alphakill
2365 if (vid.allowalphatocoverage)
2367 if (r_transparent_alphatocoverage.integer)
2369 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2370 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2373 GL_AlphaToCoverage(false);
2376 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2378 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2380 switch(rsurface.texture->offsetmapping)
2382 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2383 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2384 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2385 case OFFSETMAPPING_OFF: break;
2388 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2389 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2390 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2391 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2392 // directional model lighting
2393 mode = SHADERMODE_LIGHTDIRECTION;
2394 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2395 permutation |= SHADERPERMUTATION_GLOW;
2396 permutation |= SHADERPERMUTATION_DIFFUSE;
2397 if (specularscale > 0)
2398 permutation |= SHADERPERMUTATION_SPECULAR;
2399 if (r_refdef.fogenabled)
2400 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2401 if (rsurface.texture->colormapping)
2402 permutation |= SHADERPERMUTATION_COLORMAPPING;
2403 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2405 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2406 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2408 if (r_shadow_shadowmap2ddepthbuffer)
2409 permutation |= SHADERPERMUTATION_DEPTHRGB;
2411 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2412 permutation |= SHADERPERMUTATION_REFLECTION;
2413 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2414 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2415 if (rsurface.texture->reflectmasktexture)
2416 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2417 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2419 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2420 if (r_shadow_bouncegrid_state.directional)
2421 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2423 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2424 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2425 // when using alphatocoverage, we don't need alphakill
2426 if (vid.allowalphatocoverage)
2428 if (r_transparent_alphatocoverage.integer)
2430 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2431 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2434 GL_AlphaToCoverage(false);
2437 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2439 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2441 switch(rsurface.texture->offsetmapping)
2443 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2444 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2445 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2446 case OFFSETMAPPING_OFF: break;
2449 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2450 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2451 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2452 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2453 // ambient model lighting
2454 mode = SHADERMODE_LIGHTDIRECTION;
2455 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2456 permutation |= SHADERPERMUTATION_GLOW;
2457 if (r_refdef.fogenabled)
2458 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2459 if (rsurface.texture->colormapping)
2460 permutation |= SHADERPERMUTATION_COLORMAPPING;
2461 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2463 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2464 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2466 if (r_shadow_shadowmap2ddepthbuffer)
2467 permutation |= SHADERPERMUTATION_DEPTHRGB;
2469 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2470 permutation |= SHADERPERMUTATION_REFLECTION;
2471 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2472 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2473 if (rsurface.texture->reflectmasktexture)
2474 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2475 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2477 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2478 if (r_shadow_bouncegrid_state.directional)
2479 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2481 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2482 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2483 // when using alphatocoverage, we don't need alphakill
2484 if (vid.allowalphatocoverage)
2486 if (r_transparent_alphatocoverage.integer)
2488 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2489 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2492 GL_AlphaToCoverage(false);
2497 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2499 switch(rsurface.texture->offsetmapping)
2501 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2502 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2503 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2504 case OFFSETMAPPING_OFF: break;
2507 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2508 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2509 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2510 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2512 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2513 permutation |= SHADERPERMUTATION_GLOW;
2514 if (r_refdef.fogenabled)
2515 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2516 if (rsurface.texture->colormapping)
2517 permutation |= SHADERPERMUTATION_COLORMAPPING;
2518 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2520 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2521 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2523 if (r_shadow_shadowmap2ddepthbuffer)
2524 permutation |= SHADERPERMUTATION_DEPTHRGB;
2526 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2527 permutation |= SHADERPERMUTATION_REFLECTION;
2528 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2529 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2530 if (rsurface.texture->reflectmasktexture)
2531 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2532 if (FAKELIGHT_ENABLED)
2534 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2535 mode = SHADERMODE_FAKELIGHT;
2536 permutation |= SHADERPERMUTATION_DIFFUSE;
2537 if (specularscale > 0)
2538 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2540 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2542 // deluxemapping (light direction texture)
2543 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2544 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2546 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2547 permutation |= SHADERPERMUTATION_DIFFUSE;
2548 if (specularscale > 0)
2549 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2551 else if (r_glsl_deluxemapping.integer >= 2)
2553 // fake deluxemapping (uniform light direction in tangentspace)
2554 if (rsurface.uselightmaptexture)
2555 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2557 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2558 permutation |= SHADERPERMUTATION_DIFFUSE;
2559 if (specularscale > 0)
2560 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2562 else if (rsurface.uselightmaptexture)
2564 // ordinary lightmapping (q1bsp, q3bsp)
2565 mode = SHADERMODE_LIGHTMAP;
2569 // ordinary vertex coloring (q3bsp)
2570 mode = SHADERMODE_VERTEXCOLOR;
2572 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2574 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2575 if (r_shadow_bouncegrid_state.directional)
2576 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2578 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2579 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2580 // when using alphatocoverage, we don't need alphakill
2581 if (vid.allowalphatocoverage)
2583 if (r_transparent_alphatocoverage.integer)
2585 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2586 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2589 GL_AlphaToCoverage(false);
2592 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2593 colormod = dummy_colormod;
2594 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2595 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2596 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2597 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2598 switch(vid.renderpath)
2600 case RENDERPATH_D3D9:
2602 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);
2603 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2604 R_SetupShader_SetPermutationHLSL(mode, permutation);
2605 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2606 if (mode == SHADERMODE_LIGHTSOURCE)
2608 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2609 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2613 if (mode == SHADERMODE_LIGHTDIRECTION)
2615 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2618 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2619 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2620 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2621 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2622 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2624 if (mode == SHADERMODE_LIGHTSOURCE)
2626 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2627 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2628 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2629 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2630 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2632 // additive passes are only darkened by fog, not tinted
2633 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2634 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2638 if (mode == SHADERMODE_FLATCOLOR)
2640 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2642 else if (mode == SHADERMODE_LIGHTDIRECTION)
2644 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]);
2645 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2646 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2647 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2648 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2649 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2650 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2654 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2655 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2656 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);
2657 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2658 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2660 // additive passes are only darkened by fog, not tinted
2661 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2662 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2664 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2665 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);
2666 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2667 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2668 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2669 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2670 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2671 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2672 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2673 if (mode == SHADERMODE_WATER)
2674 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2676 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2677 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2678 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2679 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));
2680 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2681 if (rsurface.texture->pantstexture)
2682 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2684 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2685 if (rsurface.texture->shirttexture)
2686 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2688 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2689 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2690 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2691 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2692 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2693 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2694 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2695 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2696 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2697 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2699 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2700 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2701 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2702 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2704 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2705 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2706 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2707 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2708 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2709 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2710 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2711 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2712 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2713 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2714 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2715 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2716 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2717 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2718 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2719 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2720 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2721 if (rsurfacepass == RSURFPASS_BACKGROUND)
2723 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2724 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2725 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2729 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2731 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2732 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2733 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2734 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2736 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2737 if (rsurface.rtlight)
2739 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2740 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2745 case RENDERPATH_D3D10:
2746 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2748 case RENDERPATH_D3D11:
2749 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2751 case RENDERPATH_GL20:
2752 case RENDERPATH_GLES2:
2753 if (!vid.useinterleavedarrays)
2755 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);
2756 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2757 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2758 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2759 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2760 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2761 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2762 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2763 R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2764 R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2765 R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2769 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);
2770 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2772 // this has to be after RSurf_PrepareVerticesForBatch
2773 if (rsurface.batchskeletaltransform3x4buffer)
2774 permutation |= SHADERPERMUTATION_SKELETAL;
2775 R_SetupShader_SetPermutationGLSL(mode, permutation);
2776 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2777 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);
2779 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2780 if (mode == SHADERMODE_LIGHTSOURCE)
2782 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2783 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2784 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2785 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2786 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2787 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);
2789 // additive passes are only darkened by fog, not tinted
2790 if (r_glsl_permutation->loc_FogColor >= 0)
2791 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2792 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);
2796 if (mode == SHADERMODE_FLATCOLOR)
2798 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2800 else if (mode == SHADERMODE_LIGHTDIRECTION)
2802 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]);
2803 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]);
2804 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2805 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2806 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2807 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]);
2808 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]);
2812 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]);
2813 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]);
2814 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);
2815 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2816 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2818 // additive passes are only darkened by fog, not tinted
2819 if (r_glsl_permutation->loc_FogColor >= 0)
2821 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2822 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2824 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2826 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);
2827 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]);
2828 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]);
2829 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]);
2830 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]);
2831 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2832 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2833 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);
2834 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]);
2836 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2837 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2838 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2839 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]);
2840 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]);
2842 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2843 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));
2844 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2845 if (r_glsl_permutation->loc_Color_Pants >= 0)
2847 if (rsurface.texture->pantstexture)
2848 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2850 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2852 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2854 if (rsurface.texture->shirttexture)
2855 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2857 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2859 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]);
2860 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2861 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2862 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2863 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2864 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2865 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2866 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2867 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2869 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);
2870 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2871 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]);
2872 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2873 if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegrid_state.matrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
2874 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegrid_state.intensity*r_refdef.view.colorscale);
2876 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2877 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2878 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2879 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2880 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2881 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2882 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2883 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2884 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2885 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2886 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2887 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2888 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2889 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2890 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);
2891 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2892 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2893 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2894 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2895 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2896 if (rsurfacepass == RSURFPASS_BACKGROUND)
2898 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);
2899 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);
2900 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);
2904 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);
2906 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2907 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2908 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2909 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2911 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture );
2912 if (rsurface.rtlight)
2914 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2915 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2918 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegrid_state.texture);
2921 case RENDERPATH_GL11:
2922 case RENDERPATH_GL13:
2923 case RENDERPATH_GLES1:
2925 case RENDERPATH_SOFT:
2926 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);
2927 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2928 R_SetupShader_SetPermutationSoft(mode, permutation);
2929 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2930 if (mode == SHADERMODE_LIGHTSOURCE)
2932 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2933 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2934 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2935 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2936 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2937 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2939 // additive passes are only darkened by fog, not tinted
2940 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2941 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2945 if (mode == SHADERMODE_FLATCOLOR)
2947 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2949 else if (mode == SHADERMODE_LIGHTDIRECTION)
2951 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]);
2952 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2953 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2954 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2955 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2956 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]);
2957 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2961 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2962 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2963 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);
2964 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2965 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2967 // additive passes are only darkened by fog, not tinted
2968 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2969 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2971 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2972 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);
2973 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]);
2974 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]);
2975 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]);
2976 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]);
2977 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2978 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2979 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2980 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2982 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2983 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2984 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2985 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2986 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]);
2988 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2989 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));
2990 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2991 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2993 if (rsurface.texture->pantstexture)
2994 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2996 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2998 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
3000 if (rsurface.texture->shirttexture)
3001 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
3003 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
3005 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
3006 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
3007 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
3008 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
3009 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
3010 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
3011 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3012 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3013 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
3015 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
3016 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
3017 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3018 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3020 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
3021 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
3022 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
3023 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
3024 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
3025 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
3026 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
3027 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
3028 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
3029 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
3030 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
3031 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
3032 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
3033 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
3034 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
3035 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
3036 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3037 if (rsurfacepass == RSURFPASS_BACKGROUND)
3039 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
3040 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
3041 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3045 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3047 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3048 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
3049 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
3050 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
3052 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
3053 if (rsurface.rtlight)
3055 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3056 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3063 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3065 // select a permutation of the lighting shader appropriate to this
3066 // combination of texture, entity, light source, and fogging, only use the
3067 // minimum features necessary to avoid wasting rendering time in the
3068 // fragment shader on features that are not being used
3069 unsigned int permutation = 0;
3070 unsigned int mode = 0;
3071 const float *lightcolorbase = rtlight->currentcolor;
3072 float ambientscale = rtlight->ambientscale;
3073 float diffusescale = rtlight->diffusescale;
3074 float specularscale = rtlight->specularscale;
3075 // this is the location of the light in view space
3076 vec3_t viewlightorigin;
3077 // this transforms from view space (camera) to light space (cubemap)
3078 matrix4x4_t viewtolight;
3079 matrix4x4_t lighttoview;
3080 float viewtolight16f[16];
3082 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3083 if (rtlight->currentcubemap != r_texture_whitecube)
3084 permutation |= SHADERPERMUTATION_CUBEFILTER;
3085 if (diffusescale > 0)
3086 permutation |= SHADERPERMUTATION_DIFFUSE;
3087 if (specularscale > 0 && r_shadow_gloss.integer > 0)
3088 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3089 if (r_shadow_usingshadowmap2d)
3091 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3092 if (r_shadow_shadowmapvsdct)
3093 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3095 if (r_shadow_shadowmap2ddepthbuffer)
3096 permutation |= SHADERPERMUTATION_DEPTHRGB;
3098 if (vid.allowalphatocoverage)
3099 GL_AlphaToCoverage(false);
3100 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3101 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3102 Matrix4x4_Invert_Full(&viewtolight, &lighttoview);
3103 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3104 switch(vid.renderpath)
3106 case RENDERPATH_D3D9:
3108 R_SetupShader_SetPermutationHLSL(mode, permutation);
3109 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3110 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3111 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3112 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3113 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3114 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3115 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3116 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);
3117 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3118 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3120 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3121 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3122 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3123 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2ddepthtexture );
3124 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3127 case RENDERPATH_D3D10:
3128 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3130 case RENDERPATH_D3D11:
3131 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3133 case RENDERPATH_GL20:
3134 case RENDERPATH_GLES2:
3135 R_SetupShader_SetPermutationGLSL(mode, permutation);
3136 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3137 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
3138 if (r_glsl_permutation->loc_DeferredColor_Ambient >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3139 if (r_glsl_permutation->loc_DeferredColor_Diffuse >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3140 if (r_glsl_permutation->loc_DeferredColor_Specular >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3141 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]);
3142 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]);
3143 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);
3144 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]);
3145 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
3147 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
3148 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
3149 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
3150 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2ddepthtexture );
3151 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
3153 case RENDERPATH_GL11:
3154 case RENDERPATH_GL13:
3155 case RENDERPATH_GLES1:
3157 case RENDERPATH_SOFT:
3158 R_SetupShader_SetPermutationGLSL(mode, permutation);
3159 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3160 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
3161 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3162 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3163 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3164 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3165 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]);
3166 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);
3167 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3168 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3170 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3171 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3172 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3173 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2ddepthtexture );
3174 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3179 #define SKINFRAME_HASH 1024
3183 unsigned int loadsequence; // incremented each level change
3184 memexpandablearray_t array;
3185 skinframe_t *hash[SKINFRAME_HASH];
3188 r_skinframe_t r_skinframe;
3190 void R_SkinFrame_PrepareForPurge(void)
3192 r_skinframe.loadsequence++;
3193 // wrap it without hitting zero
3194 if (r_skinframe.loadsequence >= 200)
3195 r_skinframe.loadsequence = 1;
3198 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3202 // mark the skinframe as used for the purging code
3203 skinframe->loadsequence = r_skinframe.loadsequence;
3206 void R_SkinFrame_Purge(void)
3210 for (i = 0;i < SKINFRAME_HASH;i++)
3212 for (s = r_skinframe.hash[i];s;s = s->next)
3214 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3216 if (s->merged == s->base)
3218 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3219 R_PurgeTexture(s->stain );s->stain = NULL;
3220 R_PurgeTexture(s->merged);s->merged = NULL;
3221 R_PurgeTexture(s->base );s->base = NULL;
3222 R_PurgeTexture(s->pants );s->pants = NULL;
3223 R_PurgeTexture(s->shirt );s->shirt = NULL;
3224 R_PurgeTexture(s->nmap );s->nmap = NULL;
3225 R_PurgeTexture(s->gloss );s->gloss = NULL;
3226 R_PurgeTexture(s->glow );s->glow = NULL;
3227 R_PurgeTexture(s->fog );s->fog = NULL;
3228 R_PurgeTexture(s->reflect);s->reflect = NULL;
3229 s->loadsequence = 0;
3235 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3237 char basename[MAX_QPATH];
3239 Image_StripImageExtension(name, basename, sizeof(basename));
3241 if( last == NULL ) {
3243 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3244 item = r_skinframe.hash[hashindex];
3249 // linearly search through the hash bucket
3250 for( ; item ; item = item->next ) {
3251 if( !strcmp( item->basename, basename ) ) {
3258 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3262 char basename[MAX_QPATH];
3264 Image_StripImageExtension(name, basename, sizeof(basename));
3266 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3267 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3268 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3272 rtexture_t *dyntexture;
3273 // check whether its a dynamic texture
3274 dyntexture = CL_GetDynTexture( basename );
3275 if (!add && !dyntexture)
3277 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3278 memset(item, 0, sizeof(*item));
3279 strlcpy(item->basename, basename, sizeof(item->basename));
3280 item->base = dyntexture; // either NULL or dyntexture handle
3281 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3282 item->comparewidth = comparewidth;
3283 item->compareheight = compareheight;
3284 item->comparecrc = comparecrc;
3285 item->next = r_skinframe.hash[hashindex];
3286 r_skinframe.hash[hashindex] = item;
3288 else if (textureflags & TEXF_FORCE_RELOAD)
3290 rtexture_t *dyntexture;
3291 // check whether its a dynamic texture
3292 dyntexture = CL_GetDynTexture( basename );
3293 if (!add && !dyntexture)
3295 if (item->merged == item->base)
3296 item->merged = NULL;
3297 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3298 R_PurgeTexture(item->stain );item->stain = NULL;
3299 R_PurgeTexture(item->merged);item->merged = NULL;
3300 R_PurgeTexture(item->base );item->base = NULL;
3301 R_PurgeTexture(item->pants );item->pants = NULL;
3302 R_PurgeTexture(item->shirt );item->shirt = NULL;
3303 R_PurgeTexture(item->nmap );item->nmap = NULL;
3304 R_PurgeTexture(item->gloss );item->gloss = NULL;
3305 R_PurgeTexture(item->glow );item->glow = NULL;
3306 R_PurgeTexture(item->fog );item->fog = NULL;
3307 R_PurgeTexture(item->reflect);item->reflect = NULL;
3308 item->loadsequence = 0;
3310 else if( item->base == NULL )
3312 rtexture_t *dyntexture;
3313 // check whether its a dynamic texture
3314 // 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]
3315 dyntexture = CL_GetDynTexture( basename );
3316 item->base = dyntexture; // either NULL or dyntexture handle
3319 R_SkinFrame_MarkUsed(item);
3323 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3325 unsigned long long avgcolor[5], wsum; \
3333 for(pix = 0; pix < cnt; ++pix) \
3336 for(comp = 0; comp < 3; ++comp) \
3338 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3341 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3343 for(comp = 0; comp < 3; ++comp) \
3344 avgcolor[comp] += getpixel * w; \
3347 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3348 avgcolor[4] += getpixel; \
3350 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3352 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3353 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3354 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3355 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3358 extern cvar_t gl_picmip;
3359 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3362 unsigned char *pixels;
3363 unsigned char *bumppixels;
3364 unsigned char *basepixels = NULL;
3365 int basepixels_width = 0;
3366 int basepixels_height = 0;
3367 skinframe_t *skinframe;
3368 rtexture_t *ddsbase = NULL;
3369 qboolean ddshasalpha = false;
3370 float ddsavgcolor[4];
3371 char basename[MAX_QPATH];
3372 int miplevel = R_PicmipForFlags(textureflags);
3373 int savemiplevel = miplevel;
3377 if (cls.state == ca_dedicated)
3380 // return an existing skinframe if already loaded
3381 // if loading of the first image fails, don't make a new skinframe as it
3382 // would cause all future lookups of this to be missing
3383 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3384 if (skinframe && skinframe->base)
3387 Image_StripImageExtension(name, basename, sizeof(basename));
3389 // check for DDS texture file first
3390 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3392 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3393 if (basepixels == NULL)
3397 // FIXME handle miplevel
3399 if (developer_loading.integer)
3400 Con_Printf("loading skin \"%s\"\n", name);
3402 // we've got some pixels to store, so really allocate this new texture now
3404 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3405 textureflags &= ~TEXF_FORCE_RELOAD;
3406 skinframe->stain = NULL;
3407 skinframe->merged = NULL;
3408 skinframe->base = NULL;
3409 skinframe->pants = NULL;
3410 skinframe->shirt = NULL;
3411 skinframe->nmap = NULL;
3412 skinframe->gloss = NULL;
3413 skinframe->glow = NULL;
3414 skinframe->fog = NULL;
3415 skinframe->reflect = NULL;
3416 skinframe->hasalpha = false;
3417 // we could store the q2animname here too
3421 skinframe->base = ddsbase;
3422 skinframe->hasalpha = ddshasalpha;
3423 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3424 if (r_loadfog && skinframe->hasalpha)
3425 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);
3426 //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]);
3430 basepixels_width = image_width;
3431 basepixels_height = image_height;
3432 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);
3433 if (textureflags & TEXF_ALPHA)
3435 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3437 if (basepixels[j] < 255)
3439 skinframe->hasalpha = true;
3443 if (r_loadfog && skinframe->hasalpha)
3445 // has transparent pixels
3446 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3447 for (j = 0;j < image_width * image_height * 4;j += 4)
3452 pixels[j+3] = basepixels[j+3];
3454 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);
3458 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3460 //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]);
3461 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3462 R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3463 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3464 R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3470 mymiplevel = savemiplevel;
3471 if (r_loadnormalmap)
3472 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);
3473 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3475 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3476 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3477 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3478 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3481 // _norm is the name used by tenebrae and has been adopted as standard
3482 if (r_loadnormalmap && skinframe->nmap == NULL)
3484 mymiplevel = savemiplevel;
3485 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3487 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);
3491 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3493 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3494 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3495 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);
3497 Mem_Free(bumppixels);
3499 else if (r_shadow_bumpscale_basetexture.value > 0)
3501 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3502 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3503 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);
3507 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3508 R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3512 // _luma is supported only for tenebrae compatibility
3513 // _glow is the preferred name
3514 mymiplevel = savemiplevel;
3515 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))))
3517 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);
3519 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3520 R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3522 Mem_Free(pixels);pixels = NULL;
3525 mymiplevel = savemiplevel;
3526 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3528 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);
3530 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3531 R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3537 mymiplevel = savemiplevel;
3538 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3540 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);
3542 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3543 R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3549 mymiplevel = savemiplevel;
3550 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3552 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);
3554 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3555 R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3561 mymiplevel = savemiplevel;
3562 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3564 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);
3566 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3567 R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3574 Mem_Free(basepixels);
3579 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3580 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3583 skinframe_t *skinframe;
3586 if (cls.state == ca_dedicated)
3589 // if already loaded just return it, otherwise make a new skinframe
3590 skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3591 if (skinframe->base)
3593 textureflags &= ~TEXF_FORCE_RELOAD;
3595 skinframe->stain = NULL;
3596 skinframe->merged = NULL;
3597 skinframe->base = NULL;
3598 skinframe->pants = NULL;
3599 skinframe->shirt = NULL;
3600 skinframe->nmap = NULL;
3601 skinframe->gloss = NULL;
3602 skinframe->glow = NULL;
3603 skinframe->fog = NULL;
3604 skinframe->reflect = NULL;
3605 skinframe->hasalpha = false;
3607 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3611 if (developer_loading.integer)
3612 Con_Printf("loading 32bit skin \"%s\"\n", name);
3614 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3616 unsigned char *a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3617 unsigned char *b = a + width * height * 4;
3618 Image_HeightmapToNormalmap_BGRA(skindata, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3619 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, b, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3622 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3623 if (textureflags & TEXF_ALPHA)
3625 for (i = 3;i < width * height * 4;i += 4)
3627 if (skindata[i] < 255)
3629 skinframe->hasalpha = true;
3633 if (r_loadfog && skinframe->hasalpha)
3635 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3636 memcpy(fogpixels, skindata, width * height * 4);
3637 for (i = 0;i < width * height * 4;i += 4)
3638 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3639 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3640 Mem_Free(fogpixels);
3644 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3645 //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]);
3650 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3654 skinframe_t *skinframe;
3656 if (cls.state == ca_dedicated)
3659 // if already loaded just return it, otherwise make a new skinframe
3660 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3661 if (skinframe->base)
3663 //textureflags &= ~TEXF_FORCE_RELOAD;
3665 skinframe->stain = NULL;
3666 skinframe->merged = NULL;
3667 skinframe->base = NULL;
3668 skinframe->pants = NULL;
3669 skinframe->shirt = NULL;
3670 skinframe->nmap = NULL;
3671 skinframe->gloss = NULL;
3672 skinframe->glow = NULL;
3673 skinframe->fog = NULL;
3674 skinframe->reflect = NULL;
3675 skinframe->hasalpha = false;
3677 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3681 if (developer_loading.integer)
3682 Con_Printf("loading quake skin \"%s\"\n", name);
3684 // 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)
3685 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3686 memcpy(skinframe->qpixels, skindata, width*height);
3687 skinframe->qwidth = width;
3688 skinframe->qheight = height;
3691 for (i = 0;i < width * height;i++)
3692 featuresmask |= palette_featureflags[skindata[i]];
3694 skinframe->hasalpha = false;
3697 skinframe->hasalpha = true;
3698 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3699 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3700 skinframe->qgeneratemerged = true;
3701 skinframe->qgeneratebase = skinframe->qhascolormapping;
3702 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3704 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3705 //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]);
3710 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3714 unsigned char *skindata;
3717 if (!skinframe->qpixels)
3720 if (!skinframe->qhascolormapping)
3721 colormapped = false;
3725 if (!skinframe->qgeneratebase)
3730 if (!skinframe->qgeneratemerged)
3734 width = skinframe->qwidth;
3735 height = skinframe->qheight;
3736 skindata = skinframe->qpixels;
3738 if (skinframe->qgeneratenmap)
3740 unsigned char *a, *b;
3741 skinframe->qgeneratenmap = false;
3742 a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3743 b = a + width * height * 4;
3744 // use either a custom palette or the quake palette
3745 Image_Copy8bitBGRA(skindata, a, width * height, palette_bgra_complete);
3746 Image_HeightmapToNormalmap_BGRA(a, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3747 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, b, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3751 if (skinframe->qgenerateglow)
3753 skinframe->qgenerateglow = false;
3754 if (skinframe->hasalpha) // fence textures
3755 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
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, -1, palette_bgra_onlyfullbrights); // glow
3762 skinframe->qgeneratebase = false;
3763 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);
3764 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);
3765 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);
3769 skinframe->qgeneratemerged = false;
3770 if (skinframe->hasalpha) // fence textures
3771 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);
3773 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);
3776 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3778 Mem_Free(skinframe->qpixels);
3779 skinframe->qpixels = NULL;
3783 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)
3786 skinframe_t *skinframe;
3789 if (cls.state == ca_dedicated)
3792 // if already loaded just return it, otherwise make a new skinframe
3793 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3794 if (skinframe->base)
3796 textureflags &= ~TEXF_FORCE_RELOAD;
3798 skinframe->stain = NULL;
3799 skinframe->merged = NULL;
3800 skinframe->base = NULL;
3801 skinframe->pants = NULL;
3802 skinframe->shirt = NULL;
3803 skinframe->nmap = NULL;
3804 skinframe->gloss = NULL;
3805 skinframe->glow = NULL;
3806 skinframe->fog = NULL;
3807 skinframe->reflect = NULL;
3808 skinframe->hasalpha = false;
3810 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3814 if (developer_loading.integer)
3815 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3817 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3818 if (textureflags & TEXF_ALPHA)
3820 for (i = 0;i < width * height;i++)
3822 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3824 skinframe->hasalpha = true;
3828 if (r_loadfog && skinframe->hasalpha)
3829 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3832 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3833 //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]);
3838 skinframe_t *R_SkinFrame_LoadMissing(void)
3840 skinframe_t *skinframe;
3842 if (cls.state == ca_dedicated)
3845 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3846 skinframe->stain = NULL;
3847 skinframe->merged = NULL;
3848 skinframe->base = NULL;
3849 skinframe->pants = NULL;
3850 skinframe->shirt = NULL;
3851 skinframe->nmap = NULL;
3852 skinframe->gloss = NULL;
3853 skinframe->glow = NULL;
3854 skinframe->fog = NULL;
3855 skinframe->reflect = NULL;
3856 skinframe->hasalpha = false;
3858 skinframe->avgcolor[0] = rand() / RAND_MAX;
3859 skinframe->avgcolor[1] = rand() / RAND_MAX;
3860 skinframe->avgcolor[2] = rand() / RAND_MAX;
3861 skinframe->avgcolor[3] = 1;
3866 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3867 typedef struct suffixinfo_s
3870 qboolean flipx, flipy, flipdiagonal;
3873 static suffixinfo_t suffix[3][6] =
3876 {"px", false, false, false},
3877 {"nx", false, false, false},
3878 {"py", false, false, false},
3879 {"ny", false, false, false},
3880 {"pz", false, false, false},
3881 {"nz", false, false, false}
3884 {"posx", false, false, false},
3885 {"negx", false, false, false},
3886 {"posy", false, false, false},
3887 {"negy", false, false, false},
3888 {"posz", false, false, false},
3889 {"negz", false, false, false}
3892 {"rt", true, false, true},
3893 {"lf", false, true, true},
3894 {"ft", true, true, false},
3895 {"bk", false, false, false},
3896 {"up", true, false, true},
3897 {"dn", true, false, true}
3901 static int componentorder[4] = {0, 1, 2, 3};
3903 static rtexture_t *R_LoadCubemap(const char *basename)
3905 int i, j, cubemapsize;
3906 unsigned char *cubemappixels, *image_buffer;
3907 rtexture_t *cubemaptexture;
3909 // must start 0 so the first loadimagepixels has no requested width/height
3911 cubemappixels = NULL;
3912 cubemaptexture = NULL;
3913 // keep trying different suffix groups (posx, px, rt) until one loads
3914 for (j = 0;j < 3 && !cubemappixels;j++)
3916 // load the 6 images in the suffix group
3917 for (i = 0;i < 6;i++)
3919 // generate an image name based on the base and and suffix
3920 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3922 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3924 // an image loaded, make sure width and height are equal
3925 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3927 // if this is the first image to load successfully, allocate the cubemap memory
3928 if (!cubemappixels && image_width >= 1)
3930 cubemapsize = image_width;
3931 // note this clears to black, so unavailable sides are black
3932 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3934 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3936 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);
3939 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3941 Mem_Free(image_buffer);
3945 // if a cubemap loaded, upload it
3948 if (developer_loading.integer)
3949 Con_Printf("loading cubemap \"%s\"\n", basename);
3951 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);
3952 Mem_Free(cubemappixels);
3956 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3957 if (developer_loading.integer)
3959 Con_Printf("(tried tried images ");
3960 for (j = 0;j < 3;j++)
3961 for (i = 0;i < 6;i++)
3962 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3963 Con_Print(" and was unable to find any of them).\n");
3966 return cubemaptexture;
3969 rtexture_t *R_GetCubemap(const char *basename)
3972 for (i = 0;i < r_texture_numcubemaps;i++)
3973 if (r_texture_cubemaps[i] != NULL)
3974 if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3975 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3976 if (i >= MAX_CUBEMAPS || !r_main_mempool)
3977 return r_texture_whitecube;
3978 r_texture_numcubemaps++;
3979 r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3980 strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3981 r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3982 return r_texture_cubemaps[i]->texture;
3985 static void R_Main_FreeViewCache(void)
3987 if (r_refdef.viewcache.entityvisible)
3988 Mem_Free(r_refdef.viewcache.entityvisible);
3989 if (r_refdef.viewcache.world_pvsbits)
3990 Mem_Free(r_refdef.viewcache.world_pvsbits);
3991 if (r_refdef.viewcache.world_leafvisible)
3992 Mem_Free(r_refdef.viewcache.world_leafvisible);
3993 if (r_refdef.viewcache.world_surfacevisible)
3994 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3995 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3998 static void R_Main_ResizeViewCache(void)
4000 int numentities = r_refdef.scene.numentities;
4001 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
4002 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
4003 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
4004 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
4005 if (r_refdef.viewcache.maxentities < numentities)
4007 r_refdef.viewcache.maxentities = numentities;
4008 if (r_refdef.viewcache.entityvisible)
4009 Mem_Free(r_refdef.viewcache.entityvisible);
4010 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
4012 if (r_refdef.viewcache.world_numclusters != numclusters)
4014 r_refdef.viewcache.world_numclusters = numclusters;
4015 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
4016 if (r_refdef.viewcache.world_pvsbits)
4017 Mem_Free(r_refdef.viewcache.world_pvsbits);
4018 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
4020 if (r_refdef.viewcache.world_numleafs != numleafs)
4022 r_refdef.viewcache.world_numleafs = numleafs;
4023 if (r_refdef.viewcache.world_leafvisible)
4024 Mem_Free(r_refdef.viewcache.world_leafvisible);
4025 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
4027 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
4029 r_refdef.viewcache.world_numsurfaces = numsurfaces;
4030 if (r_refdef.viewcache.world_surfacevisible)
4031 Mem_Free(r_refdef.viewcache.world_surfacevisible);
4032 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
4036 extern rtexture_t *loadingscreentexture;
4037 static void gl_main_start(void)
4039 loadingscreentexture = NULL;
4040 r_texture_blanknormalmap = NULL;
4041 r_texture_white = NULL;
4042 r_texture_grey128 = NULL;
4043 r_texture_black = NULL;
4044 r_texture_whitecube = NULL;
4045 r_texture_normalizationcube = NULL;
4046 r_texture_fogattenuation = NULL;
4047 r_texture_fogheighttexture = NULL;
4048 r_texture_gammaramps = NULL;
4049 r_texture_numcubemaps = 0;
4050 r_uniformbufferalignment = 32;
4052 r_loaddds = r_texture_dds_load.integer != 0;
4053 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
4055 switch(vid.renderpath)
4057 case RENDERPATH_GL20:
4058 case RENDERPATH_D3D9:
4059 case RENDERPATH_D3D10:
4060 case RENDERPATH_D3D11:
4061 case RENDERPATH_SOFT:
4062 case RENDERPATH_GLES2:
4063 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4064 Cvar_SetValueQuick(&gl_combine, 1);
4065 Cvar_SetValueQuick(&r_glsl, 1);
4066 r_loadnormalmap = true;
4069 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
4070 if (vid.support.arb_uniform_buffer_object)
4071 qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4074 case RENDERPATH_GL13:
4075 case RENDERPATH_GLES1:
4076 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4077 Cvar_SetValueQuick(&gl_combine, 1);
4078 Cvar_SetValueQuick(&r_glsl, 0);
4079 r_loadnormalmap = false;
4080 r_loadgloss = false;
4083 case RENDERPATH_GL11:
4084 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4085 Cvar_SetValueQuick(&gl_combine, 0);
4086 Cvar_SetValueQuick(&r_glsl, 0);
4087 r_loadnormalmap = false;
4088 r_loadgloss = false;
4094 R_FrameData_Reset();
4095 R_BufferData_Reset();
4099 memset(r_queries, 0, sizeof(r_queries));
4101 r_qwskincache = NULL;
4102 r_qwskincache_size = 0;
4104 // due to caching of texture_t references, the collision cache must be reset
4105 Collision_Cache_Reset(true);
4107 // set up r_skinframe loading system for textures
4108 memset(&r_skinframe, 0, sizeof(r_skinframe));
4109 r_skinframe.loadsequence = 1;
4110 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4112 r_main_texturepool = R_AllocTexturePool();
4113 R_BuildBlankTextures();
4115 if (vid.support.arb_texture_cube_map)
4118 R_BuildNormalizationCube();
4120 r_texture_fogattenuation = NULL;
4121 r_texture_fogheighttexture = NULL;
4122 r_texture_gammaramps = NULL;
4123 //r_texture_fogintensity = NULL;
4124 memset(&r_fb, 0, sizeof(r_fb));
4125 r_glsl_permutation = NULL;
4126 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4127 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4128 glslshaderstring = NULL;
4130 r_hlsl_permutation = NULL;
4131 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4132 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4134 hlslshaderstring = NULL;
4135 memset(&r_svbsp, 0, sizeof (r_svbsp));
4137 memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4138 r_texture_numcubemaps = 0;
4140 r_refdef.fogmasktable_density = 0;
4143 // For Steelstorm Android
4144 // FIXME CACHE the program and reload
4145 // FIXME see possible combinations for SS:BR android
4146 Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
4147 R_SetupShader_SetPermutationGLSL(0, 12);
4148 R_SetupShader_SetPermutationGLSL(0, 13);
4149 R_SetupShader_SetPermutationGLSL(0, 8388621);
4150 R_SetupShader_SetPermutationGLSL(3, 0);
4151 R_SetupShader_SetPermutationGLSL(3, 2048);
4152 R_SetupShader_SetPermutationGLSL(5, 0);
4153 R_SetupShader_SetPermutationGLSL(5, 2);
4154 R_SetupShader_SetPermutationGLSL(5, 2048);
4155 R_SetupShader_SetPermutationGLSL(5, 8388608);
4156 R_SetupShader_SetPermutationGLSL(11, 1);
4157 R_SetupShader_SetPermutationGLSL(11, 2049);
4158 R_SetupShader_SetPermutationGLSL(11, 8193);
4159 R_SetupShader_SetPermutationGLSL(11, 10241);
4160 Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
4164 static void gl_main_shutdown(void)
4167 R_FrameData_Reset();
4168 R_BufferData_Reset();
4170 R_Main_FreeViewCache();
4172 switch(vid.renderpath)
4174 case RENDERPATH_GL11:
4175 case RENDERPATH_GL13:
4176 case RENDERPATH_GL20:
4177 case RENDERPATH_GLES1:
4178 case RENDERPATH_GLES2:
4179 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
4181 qglDeleteQueriesARB(r_maxqueries, r_queries);
4184 case RENDERPATH_D3D9:
4185 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4187 case RENDERPATH_D3D10:
4188 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4190 case RENDERPATH_D3D11:
4191 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4193 case RENDERPATH_SOFT:
4199 memset(r_queries, 0, sizeof(r_queries));
4201 r_qwskincache = NULL;
4202 r_qwskincache_size = 0;
4204 // clear out the r_skinframe state
4205 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4206 memset(&r_skinframe, 0, sizeof(r_skinframe));
4209 Mem_Free(r_svbsp.nodes);
4210 memset(&r_svbsp, 0, sizeof (r_svbsp));
4211 R_FreeTexturePool(&r_main_texturepool);
4212 loadingscreentexture = NULL;
4213 r_texture_blanknormalmap = NULL;
4214 r_texture_white = NULL;
4215 r_texture_grey128 = NULL;
4216 r_texture_black = NULL;
4217 r_texture_whitecube = NULL;
4218 r_texture_normalizationcube = NULL;
4219 r_texture_fogattenuation = NULL;
4220 r_texture_fogheighttexture = NULL;
4221 r_texture_gammaramps = NULL;
4222 r_texture_numcubemaps = 0;
4223 //r_texture_fogintensity = NULL;
4224 memset(&r_fb, 0, sizeof(r_fb));
4227 r_glsl_permutation = NULL;
4228 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4229 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4230 glslshaderstring = NULL;
4232 r_hlsl_permutation = NULL;
4233 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4234 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4236 hlslshaderstring = NULL;
4239 static void gl_main_newmap(void)
4241 // FIXME: move this code to client
4242 char *entities, entname[MAX_QPATH];
4244 Mem_Free(r_qwskincache);
4245 r_qwskincache = NULL;
4246 r_qwskincache_size = 0;
4249 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4250 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4252 CL_ParseEntityLump(entities);
4256 if (cl.worldmodel->brush.entities)
4257 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4259 R_Main_FreeViewCache();
4261 R_FrameData_Reset();
4262 R_BufferData_Reset();
4265 void GL_Main_Init(void)
4268 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4270 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4271 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4272 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4273 if (gamemode == GAME_NEHAHRA)
4275 Cvar_RegisterVariable (&gl_fogenable);
4276 Cvar_RegisterVariable (&gl_fogdensity);
4277 Cvar_RegisterVariable (&gl_fogred);
4278 Cvar_RegisterVariable (&gl_foggreen);
4279 Cvar_RegisterVariable (&gl_fogblue);
4280 Cvar_RegisterVariable (&gl_fogstart);
4281 Cvar_RegisterVariable (&gl_fogend);
4282 Cvar_RegisterVariable (&gl_skyclip);
4284 Cvar_RegisterVariable(&r_motionblur);
4285 Cvar_RegisterVariable(&r_damageblur);
4286 Cvar_RegisterVariable(&r_motionblur_averaging);
4287 Cvar_RegisterVariable(&r_motionblur_randomize);
4288 Cvar_RegisterVariable(&r_motionblur_minblur);
4289 Cvar_RegisterVariable(&r_motionblur_maxblur);
4290 Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4291 Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4292 Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4293 Cvar_RegisterVariable(&r_motionblur_mousefactor);
4294 Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4295 Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4296 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4297 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4298 Cvar_RegisterVariable(&r_equalize_entities_by);
4299 Cvar_RegisterVariable(&r_equalize_entities_to);
4300 Cvar_RegisterVariable(&r_depthfirst);
4301 Cvar_RegisterVariable(&r_useinfinitefarclip);
4302 Cvar_RegisterVariable(&r_farclip_base);
4303 Cvar_RegisterVariable(&r_farclip_world);
4304 Cvar_RegisterVariable(&r_nearclip);
4305 Cvar_RegisterVariable(&r_deformvertexes);
4306 Cvar_RegisterVariable(&r_transparent);
4307 Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4308 Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4309 Cvar_RegisterVariable(&r_transparent_useplanardistance);
4310 Cvar_RegisterVariable(&r_showoverdraw);
4311 Cvar_RegisterVariable(&r_showbboxes);
4312 Cvar_RegisterVariable(&r_showsurfaces);
4313 Cvar_RegisterVariable(&r_showtris);
4314 Cvar_RegisterVariable(&r_shownormals);
4315 Cvar_RegisterVariable(&r_showlighting);
4316 Cvar_RegisterVariable(&r_showshadowvolumes);
4317 Cvar_RegisterVariable(&r_showcollisionbrushes);
4318 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4319 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4320 Cvar_RegisterVariable(&r_showdisabledepthtest);
4321 Cvar_RegisterVariable(&r_drawportals);
4322 Cvar_RegisterVariable(&r_drawentities);
4323 Cvar_RegisterVariable(&r_draw2d);
4324 Cvar_RegisterVariable(&r_drawworld);
4325 Cvar_RegisterVariable(&r_cullentities_trace);
4326 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4327 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4328 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4329 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4330 Cvar_RegisterVariable(&r_sortentities);
4331 Cvar_RegisterVariable(&r_drawviewmodel);
4332 Cvar_RegisterVariable(&r_drawexteriormodel);
4333 Cvar_RegisterVariable(&r_speeds);
4334 Cvar_RegisterVariable(&r_fullbrights);
4335 Cvar_RegisterVariable(&r_wateralpha);
4336 Cvar_RegisterVariable(&r_dynamic);
4337 Cvar_RegisterVariable(&r_fakelight);
4338 Cvar_RegisterVariable(&r_fakelight_intensity);
4339 Cvar_RegisterVariable(&r_fullbright);
4340 Cvar_RegisterVariable(&r_shadows);
4341 Cvar_RegisterVariable(&r_shadows_darken);
4342 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4343 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4344 Cvar_RegisterVariable(&r_shadows_throwdistance);
4345 Cvar_RegisterVariable(&r_shadows_throwdirection);
4346 Cvar_RegisterVariable(&r_shadows_focus);
4347 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4348 Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4349 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4350 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4351 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4352 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4353 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4354 Cvar_RegisterVariable(&r_fog_exp2);
4355 Cvar_RegisterVariable(&r_fog_clear);
4356 Cvar_RegisterVariable(&r_drawfog);
4357 Cvar_RegisterVariable(&r_transparentdepthmasking);
4358 Cvar_RegisterVariable(&r_transparent_sortmindist);
4359 Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4360 Cvar_RegisterVariable(&r_transparent_sortarraysize);
4361 Cvar_RegisterVariable(&r_texture_dds_load);
4362 Cvar_RegisterVariable(&r_texture_dds_save);
4363 Cvar_RegisterVariable(&r_textureunits);
4364 Cvar_RegisterVariable(&gl_combine);
4365 Cvar_RegisterVariable(&r_usedepthtextures);
4366 Cvar_RegisterVariable(&r_viewfbo);
4367 Cvar_RegisterVariable(&r_viewscale);
4368 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4369 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4370 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4371 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4372 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4373 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4374 Cvar_RegisterVariable(&r_glsl);
4375 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4376 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4377 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4378 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4379 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4380 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4381 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4382 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4383 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4384 Cvar_RegisterVariable(&r_glsl_postprocess);
4385 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4386 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4387 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4388 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4389 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4390 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4391 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4392 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4393 Cvar_RegisterVariable(&r_celshading);
4394 Cvar_RegisterVariable(&r_celoutlines);
4396 Cvar_RegisterVariable(&r_water);
4397 Cvar_RegisterVariable(&r_water_cameraentitiesonly);
4398 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4399 Cvar_RegisterVariable(&r_water_clippingplanebias);
4400 Cvar_RegisterVariable(&r_water_refractdistort);
4401 Cvar_RegisterVariable(&r_water_reflectdistort);
4402 Cvar_RegisterVariable(&r_water_scissormode);
4403 Cvar_RegisterVariable(&r_water_lowquality);
4404 Cvar_RegisterVariable(&r_water_hideplayer);
4405 Cvar_RegisterVariable(&r_water_fbo);
4407 Cvar_RegisterVariable(&r_lerpsprites);
4408 Cvar_RegisterVariable(&r_lerpmodels);
4409 Cvar_RegisterVariable(&r_lerplightstyles);
4410 Cvar_RegisterVariable(&r_waterscroll);
4411 Cvar_RegisterVariable(&r_bloom);
4412 Cvar_RegisterVariable(&r_bloom_colorscale);
4413 Cvar_RegisterVariable(&r_bloom_brighten);
4414 Cvar_RegisterVariable(&r_bloom_blur);
4415 Cvar_RegisterVariable(&r_bloom_resolution);
4416 Cvar_RegisterVariable(&r_bloom_colorexponent);
4417 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4418 Cvar_RegisterVariable(&r_bloom_scenebrightness);
4419 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4420 Cvar_RegisterVariable(&r_hdr_glowintensity);
4421 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4422 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4423 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4424 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4425 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4426 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4427 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4428 Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4429 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4430 Cvar_RegisterVariable(&developer_texturelogging);
4431 Cvar_RegisterVariable(&gl_lightmaps);
4432 Cvar_RegisterVariable(&r_test);
4433 Cvar_RegisterVariable(&r_batch_multidraw);
4434 Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4435 Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4436 Cvar_RegisterVariable(&r_glsl_skeletal);
4437 Cvar_RegisterVariable(&r_glsl_saturation);
4438 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4439 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4440 Cvar_RegisterVariable(&r_framedatasize);
4441 for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4442 Cvar_RegisterVariable(&r_buffermegs[i]);
4443 Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4444 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4445 Cvar_SetValue("r_fullbrights", 0);
4446 #ifdef DP_MOBILETOUCH
4447 // GLES devices have terrible depth precision in general, so...
4448 Cvar_SetValueQuick(&r_nearclip, 4);
4449 Cvar_SetValueQuick(&r_farclip_base, 4096);
4450 Cvar_SetValueQuick(&r_farclip_world, 0);
4451 Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
4453 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4456 void Render_Init(void)
4469 R_LightningBeams_Init();
4479 extern char *ENGINE_EXTENSIONS;
4482 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4483 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4484 gl_version = (const char *)qglGetString(GL_VERSION);
4485 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4489 if (!gl_platformextensions)
4490 gl_platformextensions = "";
4492 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4493 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4494 Con_Printf("GL_VERSION: %s\n", gl_version);
4495 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4496 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4498 VID_CheckExtensions();
4500 // LordHavoc: report supported extensions
4502 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4504 Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
4507 // clear to black (loading plaque will be seen over this)
4508 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4512 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4516 if (r_trippy.integer)
4518 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4520 p = r_refdef.view.frustum + i;
4525 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4529 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4533 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4537 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4541 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4545 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4549 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4553 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4561 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4565 if (r_trippy.integer)
4567 for (i = 0;i < numplanes;i++)
4574 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4578 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4582 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4586 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4590 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4594 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4598 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4602 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4610 //==================================================================================
4612 // LordHavoc: this stores temporary data used within the same frame
4614 typedef struct r_framedata_mem_s
4616 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4617 size_t size; // how much usable space
4618 size_t current; // how much space in use
4619 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4620 size_t wantedsize; // how much space was allocated
4621 unsigned char *data; // start of real data (16byte aligned)
4625 static r_framedata_mem_t *r_framedata_mem;
4627 void R_FrameData_Reset(void)
4629 while (r_framedata_mem)
4631 r_framedata_mem_t *next = r_framedata_mem->purge;
4632 Mem_Free(r_framedata_mem);
4633 r_framedata_mem = next;
4637 static void R_FrameData_Resize(qboolean mustgrow)
4640 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4641 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4642 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4644 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4645 newmem->wantedsize = wantedsize;
4646 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4647 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4648 newmem->current = 0;
4650 newmem->purge = r_framedata_mem;
4651 r_framedata_mem = newmem;
4655 void R_FrameData_NewFrame(void)
4657 R_FrameData_Resize(false);
4658 if (!r_framedata_mem)
4660 // if we ran out of space on the last frame, free the old memory now
4661 while (r_framedata_mem->purge)
4663 // repeatedly remove the second item in the list, leaving only head
4664 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4665 Mem_Free(r_framedata_mem->purge);
4666 r_framedata_mem->purge = next;
4668 // reset the current mem pointer
4669 r_framedata_mem->current = 0;
4670 r_framedata_mem->mark = 0;
4673 void *R_FrameData_Alloc(size_t size)
4678 // align to 16 byte boundary - the data pointer is already aligned, so we
4679 // only need to ensure the size of every allocation is also aligned
4680 size = (size + 15) & ~15;
4682 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4684 // emergency - we ran out of space, allocate more memory
4685 // note: this has no upper-bound, we'll fail to allocate memory eventually and just die
4686 newvalue = r_framedatasize.value * 2.0f;
4687 // upper bound based on architecture - if we try to allocate more than this we could overflow, better to loop until we error out on allocation failure
4688 if (sizeof(size_t) >= 8)
4689 newvalue = bound(0.25f, newvalue, (float)(1ll << 42));
4691 newvalue = bound(0.25f, newvalue, (float)(1 << 10));
4692 // this might not be a growing it, but we'll allocate another buffer every time
4693 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4694 R_FrameData_Resize(true);
4697 data = r_framedata_mem->data + r_framedata_mem->current;
4698 r_framedata_mem->current += size;
4700 // count the usage for stats
4701 r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4702 r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4704 return (void *)data;
4707 void *R_FrameData_Store(size_t size, void *data)
4709 void *d = R_FrameData_Alloc(size);
4711 memcpy(d, data, size);
4715 void R_FrameData_SetMark(void)
4717 if (!r_framedata_mem)
4719 r_framedata_mem->mark = r_framedata_mem->current;
4722 void R_FrameData_ReturnToMark(void)
4724 if (!r_framedata_mem)
4726 r_framedata_mem->current = r_framedata_mem->mark;
4729 //==================================================================================
4731 // avoid reusing the same buffer objects on consecutive frames
4732 #define R_BUFFERDATA_CYCLE 3
4734 typedef struct r_bufferdata_buffer_s
4736 struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4737 size_t size; // how much usable space
4738 size_t current; // how much space in use
4739 r_meshbuffer_t *buffer; // the buffer itself
4741 r_bufferdata_buffer_t;
4743 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4744 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4746 /// frees all dynamic buffers
4747 void R_BufferData_Reset(void)
4750 r_bufferdata_buffer_t **p, *mem;
4751 for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4753 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4756 p = &r_bufferdata_buffer[cycle][type];
4762 R_Mesh_DestroyMeshBuffer(mem->buffer);
4769 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4770 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4772 r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4774 float newvalue = r_buffermegs[type].value;
4776 // increase the cvar if we have to (but only if we already have a mem)
4777 if (mustgrow && mem)
4779 newvalue = bound(0.25f, newvalue, 256.0f);
4780 while (newvalue * 1024*1024 < minsize)
4783 // clamp the cvar to valid range
4784 newvalue = bound(0.25f, newvalue, 256.0f);
4785 if (r_buffermegs[type].value != newvalue)
4786 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4788 // calculate size in bytes
4789 size = (size_t)(newvalue * 1024*1024);
4790 size = bound(131072, size, 256*1024*1024);
4792 // allocate a new buffer if the size is different (purge old one later)
4793 // or if we were told we must grow the buffer
4794 if (!mem || mem->size != size || mustgrow)
4796 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4799 if (type == R_BUFFERDATA_VERTEX)
4800 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4801 else if (type == R_BUFFERDATA_INDEX16)
4802 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4803 else if (type == R_BUFFERDATA_INDEX32)
4804 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4805 else if (type == R_BUFFERDATA_UNIFORM)
4806 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4807 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4808 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4812 void R_BufferData_NewFrame(void)
4815 r_bufferdata_buffer_t **p, *mem;
4816 // cycle to the next frame's buffers
4817 r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4818 // if we ran out of space on the last time we used these buffers, free the old memory now
4819 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4821 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4823 R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4824 // free all but the head buffer, this is how we recycle obsolete
4825 // buffers after they are no longer in use
4826 p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4832 R_Mesh_DestroyMeshBuffer(mem->buffer);
4835 // reset the current offset
4836 r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4841 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4843 r_bufferdata_buffer_t *mem;
4847 *returnbufferoffset = 0;
4849 // align size to a byte boundary appropriate for the buffer type, this
4850 // makes all allocations have aligned start offsets
4851 if (type == R_BUFFERDATA_UNIFORM)
4852 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4854 padsize = (datasize + 15) & ~15;
4856 // if we ran out of space in this buffer we must allocate a new one
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 R_BufferData_Resize(type, true, padsize);
4860 // if the resize did not give us enough memory, fail
4861 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)
4862 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4864 mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4865 offset = (int)mem->current;
4866 mem->current += padsize;
4868 // upload the data to the buffer at the chosen offset
4870 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4871 R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4873 // count the usage for stats
4874 r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4875 r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4877 // return the buffer offset
4878 *returnbufferoffset = offset;
4883 //==================================================================================
4885 // LordHavoc: animcache originally written by Echon, rewritten since then
4888 * Animation cache prevents re-generating mesh data for an animated model
4889 * multiple times in one frame for lighting, shadowing, reflections, etc.
4892 void R_AnimCache_Free(void)
4896 void R_AnimCache_ClearCache(void)
4899 entity_render_t *ent;
4901 for (i = 0;i < r_refdef.scene.numentities;i++)
4903 ent = r_refdef.scene.entities[i];
4904 ent->animcache_vertex3f = NULL;
4905 ent->animcache_vertex3f_vertexbuffer = NULL;
4906 ent->animcache_vertex3f_bufferoffset = 0;
4907 ent->animcache_normal3f = NULL;
4908 ent->animcache_normal3f_vertexbuffer = NULL;
4909 ent->animcache_normal3f_bufferoffset = 0;
4910 ent->animcache_svector3f = NULL;
4911 ent->animcache_svector3f_vertexbuffer = NULL;
4912 ent->animcache_svector3f_bufferoffset = 0;
4913 ent->animcache_tvector3f = NULL;
4914 ent->animcache_tvector3f_vertexbuffer = NULL;
4915 ent->animcache_tvector3f_bufferoffset = 0;
4916 ent->animcache_vertexmesh = NULL;
4917 ent->animcache_vertexmesh_vertexbuffer = NULL;
4918 ent->animcache_vertexmesh_bufferoffset = 0;
4919 ent->animcache_skeletaltransform3x4 = NULL;
4920 ent->animcache_skeletaltransform3x4buffer = NULL;
4921 ent->animcache_skeletaltransform3x4offset = 0;
4922 ent->animcache_skeletaltransform3x4size = 0;
4926 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4930 // check if we need the meshbuffers
4931 if (!vid.useinterleavedarrays)
4934 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4935 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4936 // TODO: upload vertexbuffer?
4937 if (ent->animcache_vertexmesh)
4939 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4940 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4941 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4942 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4943 for (i = 0;i < numvertices;i++)
4944 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4945 if (ent->animcache_svector3f)
4946 for (i = 0;i < numvertices;i++)
4947 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4948 if (ent->animcache_tvector3f)
4949 for (i = 0;i < numvertices;i++)
4950 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4951 if (ent->animcache_normal3f)
4952 for (i = 0;i < numvertices;i++)
4953 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4957 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4959 dp_model_t *model = ent->model;
4962 // see if this ent is worth caching
4963 if (!model || !model->Draw || !model->AnimateVertices)
4965 // nothing to cache if it contains no animations and has no skeleton
4966 if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4968 // see if it is already cached for gpuskeletal
4969 if (ent->animcache_skeletaltransform3x4)
4971 // see if it is already cached as a mesh
4972 if (ent->animcache_vertex3f)
4974 // check if we need to add normals or tangents
4975 if (ent->animcache_normal3f)
4976 wantnormals = false;
4977 if (ent->animcache_svector3f)
4978 wanttangents = false;
4979 if (!wantnormals && !wanttangents)
4983 // check which kind of cache we need to generate
4984 if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4986 // cache the skeleton so the vertex shader can use it
4987 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
4988 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
4989 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
4990 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4991 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4);
4992 // note: this can fail if the buffer is at the grow limit
4993 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
4994 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
4996 else if (ent->animcache_vertex3f)
4998 // mesh was already cached but we may need to add normals/tangents
4999 // (this only happens with multiple views, reflections, cameras, etc)
5000 if (wantnormals || wanttangents)
5002 numvertices = model->surfmesh.num_vertices;
5004 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5007 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5008 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5010 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
5011 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5012 r_refdef.stats[r_stat_animcache_shade_count] += 1;
5013 r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5014 r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5019 // generate mesh cache
5020 numvertices = model->surfmesh.num_vertices;
5021 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5023 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5026 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5027 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5029 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
5030 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5031 if (wantnormals || wanttangents)
5033 r_refdef.stats[r_stat_animcache_shade_count] += 1;
5034 r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5035 r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5037 r_refdef.stats[r_stat_animcache_shape_count] += 1;
5038 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
5039 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
5044 void R_AnimCache_CacheVisibleEntities(void)
5047 qboolean wantnormals = true;
5048 qboolean wanttangents = !r_showsurfaces.integer;
5050 switch(vid.renderpath)
5052 case RENDERPATH_GL20:
5053 case RENDERPATH_D3D9:
5054 case RENDERPATH_D3D10:
5055 case RENDERPATH_D3D11:
5056 case RENDERPATH_GLES2:
5058 case RENDERPATH_GL11:
5059 case RENDERPATH_GL13:
5060 case RENDERPATH_GLES1:
5061 wanttangents = false;
5063 case RENDERPATH_SOFT:
5067 if (r_shownormals.integer)
5068 wanttangents = wantnormals = true;
5070 // TODO: thread this
5071 // NOTE: R_PrepareRTLights() also caches entities
5073 for (i = 0;i < r_refdef.scene.numentities;i++)
5074 if (r_refdef.viewcache.entityvisible[i])
5075 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5078 //==================================================================================
5080 extern cvar_t r_overheadsprites_pushback;
5082 static void R_View_UpdateEntityLighting (void)
5085 entity_render_t *ent;
5086 vec3_t tempdiffusenormal, avg;
5087 vec_t f, fa, fd, fdd;
5088 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
5090 for (i = 0;i < r_refdef.scene.numentities;i++)
5092 ent = r_refdef.scene.entities[i];
5094 // skip unseen models
5095 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
5099 if (ent->model && ent->model == cl.worldmodel)
5101 // TODO: use modellight for r_ambient settings on world?
5102 VectorSet(ent->modellight_ambient, 0, 0, 0);
5103 VectorSet(ent->modellight_diffuse, 0, 0, 0);
5104 VectorSet(ent->modellight_lightdir, 0, 0, 1);
5108 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
5110 // aleady updated by CSQC
5111 // TODO: force modellight on BSP models in this case?
5112 VectorCopy(ent->modellight_lightdir, tempdiffusenormal);
5116 // fetch the lighting from the worldmodel data
5117 VectorClear(ent->modellight_ambient);
5118 VectorClear(ent->modellight_diffuse);
5119 VectorClear(tempdiffusenormal);
5120 if (ent->flags & RENDER_LIGHT)
5123 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5125 // complete lightning for lit sprites
5126 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
5127 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
5129 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
5130 org[2] = org[2] + r_overheadsprites_pushback.value;
5131 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5134 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
5136 if(ent->flags & RENDER_EQUALIZE)
5138 // first fix up ambient lighting...
5139 if(r_equalize_entities_minambient.value > 0)
5141 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5144 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
5145 if(fa < r_equalize_entities_minambient.value * fd)
5148 // fa'/fd' = minambient
5149 // fa'+0.25*fd' = fa+0.25*fd
5151 // fa' = fd' * minambient
5152 // fd'*(0.25+minambient) = fa+0.25*fd
5154 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
5155 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
5157 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
5158 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
5159 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
5160 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
5165 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
5167 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
5168 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5172 // adjust brightness and saturation to target
5173 avg[0] = avg[1] = avg[2] = fa / f;
5174 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
5175 avg[0] = avg[1] = avg[2] = fd / f;
5176 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
5182 VectorSet(ent->modellight_ambient, 1, 1, 1);
5185 // move the light direction into modelspace coordinates for lighting code
5186 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
5187 if(VectorLength2(ent->modellight_lightdir) == 0)
5188 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
5189 VectorNormalize(ent->modellight_lightdir);
5193 #define MAX_LINEOFSIGHTTRACES 64
5195 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5198 vec3_t boxmins, boxmaxs;
5201 dp_model_t *model = r_refdef.scene.worldmodel;
5203 if (!model || !model->brush.TraceLineOfSight)
5206 // expand the box a little
5207 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
5208 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
5209 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
5210 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
5211 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
5212 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
5214 // return true if eye is inside enlarged box
5215 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
5219 VectorCopy(eye, start);
5220 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
5221 if (model->brush.TraceLineOfSight(model, start, end))
5224 // try various random positions
5225 for (i = 0;i < numsamples;i++)
5227 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5228 if (model->brush.TraceLineOfSight(model, start, end))
5236 static void R_View_UpdateEntityVisible (void)
5241 entity_render_t *ent;
5243 if (r_refdef.envmap || r_fb.water.hideplayer)
5244 renderimask = RENDER_EXTERIORMODEL | RENDER_VIEWMODEL;
5245 else if (chase_active.integer || r_fb.water.renderingscene)
5246 renderimask = RENDER_VIEWMODEL;
5248 renderimask = RENDER_EXTERIORMODEL;
5249 if (!r_drawviewmodel.integer)
5250 renderimask |= RENDER_VIEWMODEL;
5251 if (!r_drawexteriormodel.integer)
5252 renderimask |= RENDER_EXTERIORMODEL;
5253 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5254 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5256 // worldmodel can check visibility
5257 for (i = 0;i < r_refdef.scene.numentities;i++)
5259 ent = r_refdef.scene.entities[i];
5260 if (!(ent->flags & renderimask))
5261 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)))
5262 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))
5263 r_refdef.viewcache.entityvisible[i] = true;
5268 // no worldmodel or it can't check visibility
5269 for (i = 0;i < r_refdef.scene.numentities;i++)
5271 ent = r_refdef.scene.entities[i];
5272 if (!(ent->flags & renderimask))
5273 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)))
5274 r_refdef.viewcache.entityvisible[i] = true;
5277 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
5278 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
5280 for (i = 0;i < r_refdef.scene.numentities;i++)
5282 if (!r_refdef.viewcache.entityvisible[i])
5284 ent = r_refdef.scene.entities[i];
5285 if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5287 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
5289 continue; // temp entities do pvs only
5290 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5291 ent->last_trace_visibility = realtime;
5292 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5293 r_refdef.viewcache.entityvisible[i] = 0;
5299 /// only used if skyrendermasked, and normally returns false
5300 static int R_DrawBrushModelsSky (void)
5303 entity_render_t *ent;
5306 for (i = 0;i < r_refdef.scene.numentities;i++)
5308 if (!r_refdef.viewcache.entityvisible[i])
5310 ent = r_refdef.scene.entities[i];
5311 if (!ent->model || !ent->model->DrawSky)
5313 ent->model->DrawSky(ent);
5319 static void R_DrawNoModel(entity_render_t *ent);
5320 static void R_DrawModels(void)
5323 entity_render_t *ent;
5325 for (i = 0;i < r_refdef.scene.numentities;i++)
5327 if (!r_refdef.viewcache.entityvisible[i])
5329 ent = r_refdef.scene.entities[i];
5330 r_refdef.stats[r_stat_entities]++;
5332 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5335 Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5336 Con_Printf("R_DrawModels\n");
5337 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]);
5338 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);
5339 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);
5342 if (ent->model && ent->model->Draw != NULL)
5343 ent->model->Draw(ent);
5349 static void R_DrawModelsDepth(void)
5352 entity_render_t *ent;
5354 for (i = 0;i < r_refdef.scene.numentities;i++)
5356 if (!r_refdef.viewcache.entityvisible[i])
5358 ent = r_refdef.scene.entities[i];
5359 if (ent->model && ent->model->DrawDepth != NULL)
5360 ent->model->DrawDepth(ent);
5364 static void R_DrawModelsDebug(void)
5367 entity_render_t *ent;
5369 for (i = 0;i < r_refdef.scene.numentities;i++)
5371 if (!r_refdef.viewcache.entityvisible[i])
5373 ent = r_refdef.scene.entities[i];
5374 if (ent->model && ent->model->DrawDebug != NULL)
5375 ent->model->DrawDebug(ent);
5379 static void R_DrawModelsAddWaterPlanes(void)
5382 entity_render_t *ent;
5384 for (i = 0;i < r_refdef.scene.numentities;i++)
5386 if (!r_refdef.viewcache.entityvisible[i])
5388 ent = r_refdef.scene.entities[i];
5389 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5390 ent->model->DrawAddWaterPlanes(ent);
5394 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}};
5396 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5398 if (r_hdr_irisadaptation.integer)
5403 vec3_t diffusenormal;
5405 vec_t brightness = 0.0f;
5410 VectorCopy(r_refdef.view.forward, forward);
5411 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5413 p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5414 p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5415 p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5416 R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5417 d = DotProduct(forward, diffusenormal);
5418 brightness += VectorLength(ambient);
5420 brightness += d * VectorLength(diffuse);
5422 brightness *= 1.0f / c;
5423 brightness += 0.00001f; // make sure it's never zero
5424 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5425 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5426 current = r_hdr_irisadaptation_value.value;
5428 current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5429 else if (current > goal)
5430 current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5431 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5432 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5434 else if (r_hdr_irisadaptation_value.value != 1.0f)
5435 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5438 static void R_View_SetFrustum(const int *scissor)
5441 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5442 vec3_t forward, left, up, origin, v;
5446 // flipped x coordinates (because x points left here)
5447 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5448 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5450 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5451 switch(vid.renderpath)
5453 case RENDERPATH_D3D9:
5454 case RENDERPATH_D3D10:
5455 case RENDERPATH_D3D11:
5456 // non-flipped y coordinates
5457 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5458 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5460 case RENDERPATH_SOFT:
5461 case RENDERPATH_GL11:
5462 case RENDERPATH_GL13:
5463 case RENDERPATH_GL20:
5464 case RENDERPATH_GLES1:
5465 case RENDERPATH_GLES2:
5466 // non-flipped y coordinates
5467 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5468 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5473 // we can't trust r_refdef.view.forward and friends in reflected scenes
5474 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5477 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5478 r_refdef.view.frustum[0].normal[1] = 0 - 0;
5479 r_refdef.view.frustum[0].normal[2] = -1 - 0;
5480 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5481 r_refdef.view.frustum[1].normal[1] = 0 + 0;
5482 r_refdef.view.frustum[1].normal[2] = -1 + 0;
5483 r_refdef.view.frustum[2].normal[0] = 0 - 0;
5484 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5485 r_refdef.view.frustum[2].normal[2] = -1 - 0;
5486 r_refdef.view.frustum[3].normal[0] = 0 + 0;
5487 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5488 r_refdef.view.frustum[3].normal[2] = -1 + 0;
5492 zNear = r_refdef.nearclip;
5493 nudge = 1.0 - 1.0 / (1<<23);
5494 r_refdef.view.frustum[4].normal[0] = 0 - 0;
5495 r_refdef.view.frustum[4].normal[1] = 0 - 0;
5496 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5497 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5498 r_refdef.view.frustum[5].normal[0] = 0 + 0;
5499 r_refdef.view.frustum[5].normal[1] = 0 + 0;
5500 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5501 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5507 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5508 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5509 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5510 r_refdef.view.frustum[0].dist = m[15] - m[12];
5512 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5513 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5514 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5515 r_refdef.view.frustum[1].dist = m[15] + m[12];
5517 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5518 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5519 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5520 r_refdef.view.frustum[2].dist = m[15] - m[13];
5522 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5523 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5524 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5525 r_refdef.view.frustum[3].dist = m[15] + m[13];
5527 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5528 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5529 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5530 r_refdef.view.frustum[4].dist = m[15] - m[14];
5532 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5533 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5534 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5535 r_refdef.view.frustum[5].dist = m[15] + m[14];
5538 if (r_refdef.view.useperspective)
5540 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5541 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]);
5542 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]);
5543 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]);
5544 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]);
5546 // then the normals from the corners relative to origin
5547 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5548 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5549 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5550 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5552 // in a NORMAL view, forward cross left == up
5553 // in a REFLECTED view, forward cross left == down
5554 // so our cross products above need to be adjusted for a left handed coordinate system
5555 CrossProduct(forward, left, v);
5556 if(DotProduct(v, up) < 0)
5558 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5559 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5560 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5561 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5564 // Leaving those out was a mistake, those were in the old code, and they
5565 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5566 // I couldn't reproduce it after adding those normalizations. --blub
5567 VectorNormalize(r_refdef.view.frustum[0].normal);
5568 VectorNormalize(r_refdef.view.frustum[1].normal);
5569 VectorNormalize(r_refdef.view.frustum[2].normal);
5570 VectorNormalize(r_refdef.view.frustum[3].normal);
5572 // make the corners absolute
5573 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5574 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5575 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5576 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5579 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5581 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5582 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5583 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5584 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5585 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5589 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5590 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5591 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5592 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5593 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5594 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5595 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5596 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5597 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5598 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5600 r_refdef.view.numfrustumplanes = 5;
5602 if (r_refdef.view.useclipplane)
5604 r_refdef.view.numfrustumplanes = 6;
5605 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5608 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5609 PlaneClassify(r_refdef.view.frustum + i);
5611 // LordHavoc: note to all quake engine coders, Quake had a special case
5612 // for 90 degrees which assumed a square view (wrong), so I removed it,
5613 // Quake2 has it disabled as well.
5615 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5616 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5617 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5618 //PlaneClassify(&frustum[0]);
5620 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5621 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5622 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5623 //PlaneClassify(&frustum[1]);
5625 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5626 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5627 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5628 //PlaneClassify(&frustum[2]);
5630 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5631 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5632 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5633 //PlaneClassify(&frustum[3]);
5636 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5637 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5638 //PlaneClassify(&frustum[4]);
5641 static void R_View_UpdateWithScissor(const int *myscissor)
5643 R_Main_ResizeViewCache();
5644 R_View_SetFrustum(myscissor);
5645 R_View_WorldVisibility(r_refdef.view.useclipplane);
5646 R_View_UpdateEntityVisible();
5647 R_View_UpdateEntityLighting();
5650 static void R_View_Update(void)
5652 R_Main_ResizeViewCache();
5653 R_View_SetFrustum(NULL);
5654 R_View_WorldVisibility(r_refdef.view.useclipplane);
5655 R_View_UpdateEntityVisible();
5656 R_View_UpdateEntityLighting();
5659 float viewscalefpsadjusted = 1.0f;
5661 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5663 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5664 scale = bound(0.03125f, scale, 1.0f);
5665 *outwidth = (int)ceil(width * scale);
5666 *outheight = (int)ceil(height * scale);
5669 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5671 const float *customclipplane = NULL;
5673 int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5674 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5676 // LordHavoc: couldn't figure out how to make this approach the
5677 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5678 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5679 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5680 dist = r_refdef.view.clipplane.dist;
5681 plane[0] = r_refdef.view.clipplane.normal[0];
5682 plane[1] = r_refdef.view.clipplane.normal[1];
5683 plane[2] = r_refdef.view.clipplane.normal[2];
5685 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5688 //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5689 rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5691 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5692 if (!r_refdef.view.useperspective)
5693 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);
5694 else if (vid.stencil && r_useinfinitefarclip.integer)
5695 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);
5697 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);
5698 R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5699 R_SetViewport(&r_refdef.view.viewport);
5700 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5702 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5703 float screenplane[4];
5704 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5705 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5706 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5707 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5708 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5712 void R_EntityMatrix(const matrix4x4_t *matrix)
5714 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5716 gl_modelmatrixchanged = false;
5717 gl_modelmatrix = *matrix;
5718 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5719 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5720 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5721 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5723 switch(vid.renderpath)
5725 case RENDERPATH_D3D9:
5727 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5728 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5731 case RENDERPATH_D3D10:
5732 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5734 case RENDERPATH_D3D11:
5735 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5737 case RENDERPATH_GL11:
5738 case RENDERPATH_GL13:
5739 case RENDERPATH_GLES1:
5741 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5744 case RENDERPATH_SOFT:
5745 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5746 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5748 case RENDERPATH_GL20:
5749 case RENDERPATH_GLES2:
5750 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5751 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5757 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5759 r_viewport_t viewport;
5763 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5764 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);
5765 R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5766 R_SetViewport(&viewport);
5767 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5768 GL_Color(1, 1, 1, 1);
5769 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5770 GL_BlendFunc(GL_ONE, GL_ZERO);
5771 GL_ScissorTest(false);
5772 GL_DepthMask(false);
5773 GL_DepthRange(0, 1);
5774 GL_DepthTest(false);
5775 GL_DepthFunc(GL_LEQUAL);
5776 R_EntityMatrix(&identitymatrix);
5777 R_Mesh_ResetTextureState();
5778 GL_PolygonOffset(0, 0);
5779 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5780 switch(vid.renderpath)
5782 case RENDERPATH_GL11:
5783 case RENDERPATH_GL13:
5784 case RENDERPATH_GL20:
5785 case RENDERPATH_GLES1:
5786 case RENDERPATH_GLES2:
5787 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5789 case RENDERPATH_D3D9:
5790 case RENDERPATH_D3D10:
5791 case RENDERPATH_D3D11:
5792 case RENDERPATH_SOFT:
5795 GL_CullFace(GL_NONE);
5800 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5804 R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5807 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5811 R_SetupView(true, fbo, depthtexture, colortexture);
5812 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5813 GL_Color(1, 1, 1, 1);
5814 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5815 GL_BlendFunc(GL_ONE, GL_ZERO);
5816 GL_ScissorTest(true);
5818 GL_DepthRange(0, 1);
5820 GL_DepthFunc(GL_LEQUAL);
5821 R_EntityMatrix(&identitymatrix);
5822 R_Mesh_ResetTextureState();
5823 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5824 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5825 switch(vid.renderpath)
5827 case RENDERPATH_GL11:
5828 case RENDERPATH_GL13:
5829 case RENDERPATH_GL20:
5830 case RENDERPATH_GLES1:
5831 case RENDERPATH_GLES2:
5832 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5834 case RENDERPATH_D3D9:
5835 case RENDERPATH_D3D10:
5836 case RENDERPATH_D3D11:
5837 case RENDERPATH_SOFT:
5840 GL_CullFace(r_refdef.view.cullface_back);
5845 R_RenderView_UpdateViewVectors
5848 void R_RenderView_UpdateViewVectors(void)
5850 // break apart the view matrix into vectors for various purposes
5851 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5852 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5853 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5854 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5855 // make an inverted copy of the view matrix for tracking sprites
5856 Matrix4x4_Invert_Full(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5859 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5860 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5862 static void R_Water_StartFrame(void)
5865 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5866 r_waterstate_waterplane_t *p;
5867 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;
5869 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5872 switch(vid.renderpath)
5874 case RENDERPATH_GL20:
5875 case RENDERPATH_D3D9:
5876 case RENDERPATH_D3D10:
5877 case RENDERPATH_D3D11:
5878 case RENDERPATH_SOFT:
5879 case RENDERPATH_GLES2:
5881 case RENDERPATH_GL11:
5882 case RENDERPATH_GL13:
5883 case RENDERPATH_GLES1:
5887 // set waterwidth and waterheight to the water resolution that will be
5888 // used (often less than the screen resolution for faster rendering)
5889 R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5891 // calculate desired texture sizes
5892 // can't use water if the card does not support the texture size
5893 if (!r_water.integer || r_showsurfaces.integer)
5894 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5895 else if (vid.support.arb_texture_non_power_of_two)
5897 texturewidth = waterwidth;
5898 textureheight = waterheight;
5899 camerawidth = waterwidth;
5900 cameraheight = waterheight;
5904 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5905 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5906 for (camerawidth = 1;camerawidth * 2 <= waterwidth ;camerawidth *= 2);
5907 for (cameraheight = 1;cameraheight * 2 <= waterheight;cameraheight *= 2);
5910 // allocate textures as needed
5911 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))
5913 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5914 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5916 if (p->texture_refraction)
5917 R_FreeTexture(p->texture_refraction);
5918 p->texture_refraction = NULL;
5919 if (p->fbo_refraction)
5920 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5921 p->fbo_refraction = 0;
5922 if (p->texture_reflection)
5923 R_FreeTexture(p->texture_reflection);
5924 p->texture_reflection = NULL;
5925 if (p->fbo_reflection)
5926 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5927 p->fbo_reflection = 0;
5928 if (p->texture_camera)
5929 R_FreeTexture(p->texture_camera);
5930 p->texture_camera = NULL;
5932 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5935 memset(&r_fb.water, 0, sizeof(r_fb.water));
5936 r_fb.water.texturewidth = texturewidth;
5937 r_fb.water.textureheight = textureheight;
5938 r_fb.water.camerawidth = camerawidth;
5939 r_fb.water.cameraheight = cameraheight;
5942 if (r_fb.water.texturewidth)
5944 int scaledwidth, scaledheight;
5946 r_fb.water.enabled = true;
5948 // water resolution is usually reduced
5949 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5950 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5951 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5953 // set up variables that will be used in shader setup
5954 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5955 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5956 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5957 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5960 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5961 r_fb.water.numwaterplanes = 0;
5964 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5966 int planeindex, bestplaneindex, vertexindex;
5967 vec3_t mins, maxs, normal, center, v, n;
5968 vec_t planescore, bestplanescore;
5970 r_waterstate_waterplane_t *p;
5971 texture_t *t = R_GetCurrentTexture(surface->texture);
5973 rsurface.texture = t;
5974 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5975 // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5976 if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5978 // average the vertex normals, find the surface bounds (after deformvertexes)
5979 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5980 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5981 VectorCopy(n, normal);
5982 VectorCopy(v, mins);
5983 VectorCopy(v, maxs);
5984 for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5986 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5987 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5988 VectorAdd(normal, n, normal);
5989 mins[0] = min(mins[0], v[0]);
5990 mins[1] = min(mins[1], v[1]);
5991 mins[2] = min(mins[2], v[2]);
5992 maxs[0] = max(maxs[0], v[0]);
5993 maxs[1] = max(maxs[1], v[1]);
5994 maxs[2] = max(maxs[2], v[2]);
5996 VectorNormalize(normal);
5997 VectorMAM(0.5f, mins, 0.5f, maxs, center);
5999 VectorCopy(normal, plane.normal);
6000 VectorNormalize(plane.normal);
6001 plane.dist = DotProduct(center, plane.normal);
6002 PlaneClassify(&plane);
6003 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
6005 // skip backfaces (except if nocullface is set)
6006 // if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
6008 VectorNegate(plane.normal, plane.normal);
6010 PlaneClassify(&plane);
6014 // find a matching plane if there is one
6015 bestplaneindex = -1;
6016 bestplanescore = 1048576.0f;
6017 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6019 if(p->camera_entity == t->camera_entity)
6021 planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
6022 if (bestplaneindex < 0 || bestplanescore > planescore)
6024 bestplaneindex = planeindex;
6025 bestplanescore = planescore;
6029 planeindex = bestplaneindex;
6031 // if this surface does not fit any known plane rendered this frame, add one
6032 if (planeindex < 0 || bestplanescore > 0.001f)
6034 if (r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
6036 // store the new plane
6037 planeindex = r_fb.water.numwaterplanes++;
6038 p = r_fb.water.waterplanes + planeindex;
6040 // clear materialflags and pvs
6041 p->materialflags = 0;
6042 p->pvsvalid = false;
6043 p->camera_entity = t->camera_entity;
6044 VectorCopy(mins, p->mins);
6045 VectorCopy(maxs, p->maxs);
6049 // We're totally screwed.
6055 // merge mins/maxs when we're adding this surface to the plane
6056 p = r_fb.water.waterplanes + planeindex;
6057 p->mins[0] = min(p->mins[0], mins[0]);
6058 p->mins[1] = min(p->mins[1], mins[1]);
6059 p->mins[2] = min(p->mins[2], mins[2]);
6060 p->maxs[0] = max(p->maxs[0], maxs[0]);
6061 p->maxs[1] = max(p->maxs[1], maxs[1]);
6062 p->maxs[2] = max(p->maxs[2], maxs[2]);
6064 // merge this surface's materialflags into the waterplane
6065 p->materialflags |= t->currentmaterialflags;
6066 if(!(p->materialflags & MATERIALFLAG_CAMERA))
6068 // merge this surface's PVS into the waterplane
6069 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6070 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6072 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6078 extern cvar_t r_drawparticles;
6079 extern cvar_t r_drawdecals;
6081 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6084 r_refdef_view_t originalview;
6085 r_refdef_view_t myview;
6086 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;
6087 r_waterstate_waterplane_t *p;
6089 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;
6092 originalview = r_refdef.view;
6094 // lowquality hack, temporarily shut down some cvars and restore afterwards
6095 qualityreduction = r_water_lowquality.integer;
6096 if (qualityreduction > 0)
6098 if (qualityreduction >= 1)
6100 old_r_shadows = r_shadows.integer;
6101 old_r_worldrtlight = r_shadow_realtime_world.integer;
6102 old_r_dlight = r_shadow_realtime_dlight.integer;
6103 Cvar_SetValueQuick(&r_shadows, 0);
6104 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6105 Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6107 if (qualityreduction >= 2)
6109 old_r_dynamic = r_dynamic.integer;
6110 old_r_particles = r_drawparticles.integer;
6111 old_r_decals = r_drawdecals.integer;
6112 Cvar_SetValueQuick(&r_dynamic, 0);
6113 Cvar_SetValueQuick(&r_drawparticles, 0);
6114 Cvar_SetValueQuick(&r_drawdecals, 0);
6118 // make sure enough textures are allocated
6119 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6121 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6123 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6125 if (!p->texture_refraction)
6126 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);
6127 if (!p->texture_refraction)
6131 if (r_fb.water.depthtexture == NULL)
6132 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6133 if (p->fbo_refraction == 0)
6134 p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6137 else if (p->materialflags & MATERIALFLAG_CAMERA)
6139 if (!p->texture_camera)
6140 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);
6141 if (!p->texture_camera)
6145 if (r_fb.water.depthtexture == NULL)
6146 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6147 if (p->fbo_camera == 0)
6148 p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6152 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6154 if (!p->texture_reflection)
6155 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);
6156 if (!p->texture_reflection)
6160 if (r_fb.water.depthtexture == NULL)
6161 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6162 if (p->fbo_reflection == 0)
6163 p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6169 r_refdef.view = originalview;
6170 r_refdef.view.showdebug = false;
6171 r_refdef.view.width = r_fb.water.waterwidth;
6172 r_refdef.view.height = r_fb.water.waterheight;
6173 r_refdef.view.useclipplane = true;
6174 myview = r_refdef.view;
6175 r_fb.water.renderingscene = true;
6176 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6178 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6180 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6182 r_refdef.view = myview;
6183 if(r_water_scissormode.integer)
6185 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6186 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6187 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6190 // render reflected scene and copy into texture
6191 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6192 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6193 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6194 r_refdef.view.clipplane = p->plane;
6195 // reverse the cullface settings for this render
6196 r_refdef.view.cullface_front = GL_FRONT;
6197 r_refdef.view.cullface_back = GL_BACK;
6198 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6200 r_refdef.view.usecustompvs = true;
6202 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6204 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6207 r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
6208 R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6209 R_ClearScreen(r_refdef.fogenabled);
6210 if(r_water_scissormode.integer & 2)
6211 R_View_UpdateWithScissor(myscissor);
6214 R_AnimCache_CacheVisibleEntities();
6215 if(r_water_scissormode.integer & 1)
6216 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6217 R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6219 if (!p->fbo_reflection)
6220 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);
6221 r_fb.water.hideplayer = false;
6224 // render the normal view scene and copy into texture
6225 // (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)
6226 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6228 r_refdef.view = myview;
6229 if(r_water_scissormode.integer)
6231 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6232 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6233 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6236 r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
6238 r_refdef.view.clipplane = p->plane;
6239 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6240 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6242 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6244 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6245 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6246 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6247 R_RenderView_UpdateViewVectors();
6248 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6250 r_refdef.view.usecustompvs = true;
6251 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);
6255 PlaneClassify(&r_refdef.view.clipplane);
6257 R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6258 R_ClearScreen(r_refdef.fogenabled);
6259 if(r_water_scissormode.integer & 2)
6260 R_View_UpdateWithScissor(myscissor);
6263 R_AnimCache_CacheVisibleEntities();
6264 if(r_water_scissormode.integer & 1)
6265 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6266 R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6268 if (!p->fbo_refraction)
6269 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);
6270 r_fb.water.hideplayer = false;
6272 else if (p->materialflags & MATERIALFLAG_CAMERA)
6274 r_refdef.view = myview;
6276 r_refdef.view.clipplane = p->plane;
6277 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6278 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6280 r_refdef.view.width = r_fb.water.camerawidth;
6281 r_refdef.view.height = r_fb.water.cameraheight;
6282 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6283 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6284 r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6285 r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6287 if(p->camera_entity)
6289 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6290 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6293 // note: all of the view is used for displaying... so
6294 // there is no use in scissoring
6296 // reverse the cullface settings for this render
6297 r_refdef.view.cullface_front = GL_FRONT;
6298 r_refdef.view.cullface_back = GL_BACK;
6299 // also reverse the view matrix
6300 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
6301 R_RenderView_UpdateViewVectors();
6302 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6304 r_refdef.view.usecustompvs = true;
6305 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);
6308 // camera needs no clipplane
6309 r_refdef.view.useclipplane = false;
6311 PlaneClassify(&r_refdef.view.clipplane);
6313 r_fb.water.hideplayer = false;
6315 R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6316 R_ClearScreen(r_refdef.fogenabled);
6318 R_AnimCache_CacheVisibleEntities();
6319 R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6322 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);
6323 r_fb.water.hideplayer = false;
6327 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6328 r_fb.water.renderingscene = false;
6329 r_refdef.view = originalview;
6330 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6331 if (!r_fb.water.depthtexture)
6332 R_ClearScreen(r_refdef.fogenabled);
6334 R_AnimCache_CacheVisibleEntities();
6337 r_refdef.view = originalview;
6338 r_fb.water.renderingscene = false;
6339 Cvar_SetValueQuick(&r_water, 0);
6340 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
6342 // lowquality hack, restore cvars
6343 if (qualityreduction > 0)
6345 if (qualityreduction >= 1)
6347 Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6348 Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6349 Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6351 if (qualityreduction >= 2)
6353 Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6354 Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6355 Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6360 static void R_Bloom_StartFrame(void)
6363 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6364 int viewwidth, viewheight;
6365 qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6366 textype_t textype = TEXTYPE_COLORBUFFER;
6368 switch (vid.renderpath)
6370 case RENDERPATH_GL20:
6371 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6372 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6374 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6375 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6378 case RENDERPATH_GL11:
6379 case RENDERPATH_GL13:
6380 case RENDERPATH_GLES1:
6381 case RENDERPATH_GLES2:
6382 case RENDERPATH_D3D9:
6383 case RENDERPATH_D3D10:
6384 case RENDERPATH_D3D11:
6385 r_fb.usedepthtextures = false;
6387 case RENDERPATH_SOFT:
6388 r_fb.usedepthtextures = true;
6392 if (r_viewscale_fpsscaling.integer)
6394 double actualframetime;
6395 double targetframetime;
6397 actualframetime = r_refdef.lastdrawscreentime;
6398 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6399 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6400 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6401 if (r_viewscale_fpsscaling_stepsize.value > 0)
6402 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6403 viewscalefpsadjusted += adjust;
6404 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6407 viewscalefpsadjusted = 1.0f;
6409 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6411 switch(vid.renderpath)
6413 case RENDERPATH_GL20:
6414 case RENDERPATH_D3D9:
6415 case RENDERPATH_D3D10:
6416 case RENDERPATH_D3D11:
6417 case RENDERPATH_SOFT:
6418 case RENDERPATH_GLES2:
6420 case RENDERPATH_GL11:
6421 case RENDERPATH_GL13:
6422 case RENDERPATH_GLES1:
6426 // set bloomwidth and bloomheight to the bloom resolution that will be
6427 // used (often less than the screen resolution for faster rendering)
6428 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6429 r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6430 r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6431 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6432 r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6434 // calculate desired texture sizes
6435 if (vid.support.arb_texture_non_power_of_two)
6437 screentexturewidth = vid.width;
6438 screentextureheight = vid.height;
6439 bloomtexturewidth = r_fb.bloomwidth;
6440 bloomtextureheight = r_fb.bloomheight;
6444 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
6445 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
6446 for (bloomtexturewidth = 1;bloomtexturewidth < r_fb.bloomwidth ;bloomtexturewidth *= 2);
6447 for (bloomtextureheight = 1;bloomtextureheight < r_fb.bloomheight;bloomtextureheight *= 2);
6450 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))
6452 Cvar_SetValueQuick(&r_bloom, 0);
6453 Cvar_SetValueQuick(&r_motionblur, 0);
6454 Cvar_SetValueQuick(&r_damageblur, 0);
6457 if (!((r_glsl_postprocess.integer || r_fxaa.integer) || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6459 && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6461 && r_viewscale.value == 1.0f
6462 && !r_viewscale_fpsscaling.integer)
6463 screentexturewidth = screentextureheight = 0;
6464 if (!r_bloom.integer)
6465 bloomtexturewidth = bloomtextureheight = 0;
6467 // allocate textures as needed
6468 if (r_fb.screentexturewidth != screentexturewidth
6469 || r_fb.screentextureheight != screentextureheight
6470 || r_fb.bloomtexturewidth != bloomtexturewidth
6471 || r_fb.bloomtextureheight != bloomtextureheight
6472 || r_fb.textype != textype
6473 || useviewfbo != (r_fb.fbo != 0))
6475 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6477 if (r_fb.bloomtexture[i])
6478 R_FreeTexture(r_fb.bloomtexture[i]);
6479 r_fb.bloomtexture[i] = NULL;
6481 if (r_fb.bloomfbo[i])
6482 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6483 r_fb.bloomfbo[i] = 0;
6487 R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6490 if (r_fb.colortexture)
6491 R_FreeTexture(r_fb.colortexture);
6492 r_fb.colortexture = NULL;
6494 if (r_fb.depthtexture)
6495 R_FreeTexture(r_fb.depthtexture);
6496 r_fb.depthtexture = NULL;
6498 if (r_fb.ghosttexture)
6499 R_FreeTexture(r_fb.ghosttexture);
6500 r_fb.ghosttexture = NULL;
6502 r_fb.screentexturewidth = screentexturewidth;
6503 r_fb.screentextureheight = screentextureheight;
6504 r_fb.bloomtexturewidth = bloomtexturewidth;
6505 r_fb.bloomtextureheight = bloomtextureheight;
6506 r_fb.textype = textype;
6508 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6510 if (r_motionblur.value > 0 || r_damageblur.value > 0)
6511 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);
6512 r_fb.ghosttexture_valid = false;
6513 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);
6516 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6517 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6518 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6522 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6524 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6526 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);
6528 r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6533 // bloom texture is a different resolution
6534 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6535 r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6536 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6537 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6538 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6540 // set up a texcoord array for the full resolution screen image
6541 // (we have to keep this around to copy back during final render)
6542 r_fb.screentexcoord2f[0] = 0;
6543 r_fb.screentexcoord2f[1] = (float)viewheight / (float)r_fb.screentextureheight;
6544 r_fb.screentexcoord2f[2] = (float)viewwidth / (float)r_fb.screentexturewidth;
6545 r_fb.screentexcoord2f[3] = (float)viewheight / (float)r_fb.screentextureheight;
6546 r_fb.screentexcoord2f[4] = (float)viewwidth / (float)r_fb.screentexturewidth;
6547 r_fb.screentexcoord2f[5] = 0;
6548 r_fb.screentexcoord2f[6] = 0;
6549 r_fb.screentexcoord2f[7] = 0;
6553 for (i = 1;i < 8;i += 2)
6555 r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6559 // set up a texcoord array for the reduced resolution bloom image
6560 // (which will be additive blended over the screen image)
6561 r_fb.bloomtexcoord2f[0] = 0;
6562 r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6563 r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6564 r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6565 r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6566 r_fb.bloomtexcoord2f[5] = 0;
6567 r_fb.bloomtexcoord2f[6] = 0;
6568 r_fb.bloomtexcoord2f[7] = 0;
6570 switch(vid.renderpath)
6572 case RENDERPATH_GL11:
6573 case RENDERPATH_GL13:
6574 case RENDERPATH_GL20:
6575 case RENDERPATH_SOFT:
6576 case RENDERPATH_GLES1:
6577 case RENDERPATH_GLES2:
6579 case RENDERPATH_D3D9:
6580 case RENDERPATH_D3D10:
6581 case RENDERPATH_D3D11:
6582 for (i = 0;i < 4;i++)
6584 r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6585 r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6586 r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6587 r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6592 R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6595 r_refdef.view.clear = true;
6598 static void R_Bloom_MakeTexture(void)
6601 float xoffset, yoffset, r, brighten;
6603 float colorscale = r_bloom_colorscale.value;
6605 r_refdef.stats[r_stat_bloom]++;
6608 // this copy is unnecessary since it happens in R_BlendView already
6611 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);
6612 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6616 // scale down screen texture to the bloom texture size
6618 r_fb.bloomindex = 0;
6619 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6620 R_SetViewport(&r_fb.bloomviewport);
6621 GL_DepthTest(false);
6622 GL_BlendFunc(GL_ONE, GL_ZERO);
6623 GL_Color(colorscale, colorscale, colorscale, 1);
6624 // 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...
6625 switch(vid.renderpath)
6627 case RENDERPATH_GL11:
6628 case RENDERPATH_GL13:
6629 case RENDERPATH_GL20:
6630 case RENDERPATH_GLES1:
6631 case RENDERPATH_GLES2:
6632 case RENDERPATH_SOFT:
6633 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6635 case RENDERPATH_D3D9:
6636 case RENDERPATH_D3D10:
6637 case RENDERPATH_D3D11:
6638 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6641 // TODO: do boxfilter scale-down in shader?
6642 R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6643 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6644 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6646 // we now have a properly scaled bloom image
6647 if (!r_fb.bloomfbo[r_fb.bloomindex])
6649 // copy it into the bloom texture
6650 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);
6651 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6654 // multiply bloom image by itself as many times as desired
6655 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6657 intex = r_fb.bloomtexture[r_fb.bloomindex];
6658 r_fb.bloomindex ^= 1;
6659 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6661 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6662 if (!r_fb.bloomfbo[r_fb.bloomindex])
6664 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6665 GL_Color(r,r,r,1); // apply fix factor
6670 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6671 GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6672 GL_Color(1,1,1,1); // no fix factor supported here
6674 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6675 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6676 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6677 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6679 if (!r_fb.bloomfbo[r_fb.bloomindex])
6681 // copy the darkened image to a texture
6682 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);
6683 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6687 range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6688 brighten = r_bloom_brighten.value;
6689 brighten = sqrt(brighten);
6691 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6693 for (dir = 0;dir < 2;dir++)
6695 intex = r_fb.bloomtexture[r_fb.bloomindex];
6696 r_fb.bloomindex ^= 1;
6697 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6698 // blend on at multiple vertical offsets to achieve a vertical blur
6699 // TODO: do offset blends using GLSL
6700 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6701 GL_BlendFunc(GL_ONE, GL_ZERO);
6702 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6703 for (x = -range;x <= range;x++)
6705 if (!dir){xoffset = 0;yoffset = x;}
6706 else {xoffset = x;yoffset = 0;}
6707 xoffset /= (float)r_fb.bloomtexturewidth;
6708 yoffset /= (float)r_fb.bloomtextureheight;
6709 // compute a texcoord array with the specified x and y offset
6710 r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6711 r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6712 r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6713 r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6714 r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6715 r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6716 r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6717 r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6718 // this r value looks like a 'dot' particle, fading sharply to
6719 // black at the edges
6720 // (probably not realistic but looks good enough)
6721 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6722 //r = brighten/(range*2+1);
6723 r = brighten / (range * 2 + 1);
6725 r *= (1 - x*x/(float)(range*range));
6726 GL_Color(r, r, r, 1);
6727 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6728 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6729 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6730 GL_BlendFunc(GL_ONE, GL_ONE);
6733 if (!r_fb.bloomfbo[r_fb.bloomindex])
6735 // copy the vertically or horizontally blurred bloom view to a texture
6736 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);
6737 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6742 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6744 unsigned int permutation;
6745 float uservecs[4][4];
6747 R_EntityMatrix(&identitymatrix);
6749 switch (vid.renderpath)
6751 case RENDERPATH_GL20:
6752 case RENDERPATH_D3D9:
6753 case RENDERPATH_D3D10:
6754 case RENDERPATH_D3D11:
6755 case RENDERPATH_SOFT:
6756 case RENDERPATH_GLES2:
6758 (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6759 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6760 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6761 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6762 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6764 if (r_fb.colortexture)
6768 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);
6769 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6772 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6774 // declare variables
6775 float blur_factor, blur_mouseaccel, blur_velocity;
6776 static float blur_average;
6777 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6779 // set a goal for the factoring
6780 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value)
6781 / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6782 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value)
6783 / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6784 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value)
6785 + (blur_mouseaccel * r_motionblur_mousefactor.value));
6787 // from the goal, pick an averaged value between goal and last value
6788 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6789 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6791 // enforce minimum amount of blur
6792 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6794 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6796 // calculate values into a standard alpha
6797 cl.motionbluralpha = 1 - exp(-
6799 (r_motionblur.value * blur_factor / 80)
6801 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6804 max(0.0001, cl.time - cl.oldtime) // fps independent
6807 // randomization for the blur value to combat persistent ghosting
6808 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6809 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6812 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6813 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6815 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6816 GL_Color(1, 1, 1, cl.motionbluralpha);
6817 switch(vid.renderpath)
6819 case RENDERPATH_GL11:
6820 case RENDERPATH_GL13:
6821 case RENDERPATH_GL20:
6822 case RENDERPATH_GLES1:
6823 case RENDERPATH_GLES2:
6824 case RENDERPATH_SOFT:
6825 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6827 case RENDERPATH_D3D9:
6828 case RENDERPATH_D3D10:
6829 case RENDERPATH_D3D11:
6830 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6833 R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6834 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6835 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6838 // updates old view angles for next pass
6839 VectorCopy(cl.viewangles, blur_oldangles);
6841 // copy view into the ghost texture
6842 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);
6843 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6844 r_fb.ghosttexture_valid = true;
6849 // no r_fb.colortexture means we're rendering to the real fb
6850 // we may still have to do view tint...
6851 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6853 // apply a color tint to the whole view
6854 R_ResetViewRendering2D(0, NULL, NULL);
6855 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6856 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6857 R_SetupShader_Generic_NoTexture(false, true);
6858 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6859 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6861 break; // no screen processing, no bloom, skip it
6864 if (r_fb.bloomtexture[0])
6866 // make the bloom texture
6867 R_Bloom_MakeTexture();
6870 #if _MSC_VER >= 1400
6871 #define sscanf sscanf_s
6873 memset(uservecs, 0, sizeof(uservecs));
6874 if (r_glsl_postprocess_uservec1_enable.integer)
6875 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6876 if (r_glsl_postprocess_uservec2_enable.integer)
6877 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6878 if (r_glsl_postprocess_uservec3_enable.integer)
6879 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6880 if (r_glsl_postprocess_uservec4_enable.integer)
6881 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6883 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6884 GL_Color(1, 1, 1, 1);
6885 GL_BlendFunc(GL_ONE, GL_ZERO);
6887 switch(vid.renderpath)
6889 case RENDERPATH_GL20:
6890 case RENDERPATH_GLES2:
6891 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6892 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6893 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_fb.colortexture);
6894 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_fb.bloomtexture[r_fb.bloomindex]);
6895 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6896 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]);
6897 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6898 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]);
6899 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]);
6900 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]);
6901 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]);
6902 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6903 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6904 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);
6906 case RENDERPATH_D3D9:
6908 // 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...
6909 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6910 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6911 R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture);
6912 R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]);
6913 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6914 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6915 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6916 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6917 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6918 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6919 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6920 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6921 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6922 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6925 case RENDERPATH_D3D10:
6926 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6928 case RENDERPATH_D3D11:
6929 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6931 case RENDERPATH_SOFT:
6932 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6933 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6934 R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture);
6935 R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]);
6936 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6937 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6938 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6939 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6940 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6941 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6942 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6943 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6944 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6945 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6950 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6951 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6953 case RENDERPATH_GL11:
6954 case RENDERPATH_GL13:
6955 case RENDERPATH_GLES1:
6956 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6958 // apply a color tint to the whole view
6959 R_ResetViewRendering2D(0, NULL, NULL);
6960 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6961 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6962 R_SetupShader_Generic_NoTexture(false, true);
6963 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6964 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6970 matrix4x4_t r_waterscrollmatrix;
6972 void R_UpdateFog(void)
6975 if (gamemode == GAME_NEHAHRA)
6977 if (gl_fogenable.integer)
6979 r_refdef.oldgl_fogenable = true;
6980 r_refdef.fog_density = gl_fogdensity.value;
6981 r_refdef.fog_red = gl_fogred.value;
6982 r_refdef.fog_green = gl_foggreen.value;
6983 r_refdef.fog_blue = gl_fogblue.value;
6984 r_refdef.fog_alpha = 1;
6985 r_refdef.fog_start = 0;
6986 r_refdef.fog_end = gl_skyclip.value;
6987 r_refdef.fog_height = 1<<30;
6988 r_refdef.fog_fadedepth = 128;
6990 else if (r_refdef.oldgl_fogenable)
6992 r_refdef.oldgl_fogenable = false;
6993 r_refdef.fog_density = 0;
6994 r_refdef.fog_red = 0;
6995 r_refdef.fog_green = 0;
6996 r_refdef.fog_blue = 0;
6997 r_refdef.fog_alpha = 0;
6998 r_refdef.fog_start = 0;
6999 r_refdef.fog_end = 0;
7000 r_refdef.fog_height = 1<<30;
7001 r_refdef.fog_fadedepth = 128;
7006 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
7007 r_refdef.fog_start = max(0, r_refdef.fog_start);
7008 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
7010 if (r_refdef.fog_density && r_drawfog.integer)
7012 r_refdef.fogenabled = true;
7013 // this is the point where the fog reaches 0.9986 alpha, which we
7014 // consider a good enough cutoff point for the texture
7015 // (0.9986 * 256 == 255.6)
7016 if (r_fog_exp2.integer)
7017 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
7019 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
7020 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
7021 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
7022 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
7023 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
7024 R_BuildFogHeightTexture();
7025 // fog color was already set
7026 // update the fog texture
7027 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)
7028 R_BuildFogTexture();
7029 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
7030 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
7033 r_refdef.fogenabled = false;
7036 if (r_refdef.fog_density)
7038 r_refdef.fogcolor[0] = r_refdef.fog_red;
7039 r_refdef.fogcolor[1] = r_refdef.fog_green;
7040 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7042 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7043 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7044 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7045 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7049 VectorCopy(r_refdef.fogcolor, fogvec);
7050 // color.rgb *= ContrastBoost * SceneBrightness;
7051 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7052 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7053 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7054 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7059 void R_UpdateVariables(void)
7063 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7065 r_refdef.farclip = r_farclip_base.value;
7066 if (r_refdef.scene.worldmodel)
7067 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7068 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7070 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7071 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7072 r_refdef.polygonfactor = 0;
7073 r_refdef.polygonoffset = 0;
7074 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7075 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7077 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7078 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7079 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
7080 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7081 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7082 if (FAKELIGHT_ENABLED)
7084 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
7086 else if (r_refdef.scene.worldmodel)
7088 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
7090 if (r_showsurfaces.integer)
7092 r_refdef.scene.rtworld = false;
7093 r_refdef.scene.rtworldshadows = false;
7094 r_refdef.scene.rtdlight = false;
7095 r_refdef.scene.rtdlightshadows = false;
7096 r_refdef.lightmapintensity = 0;
7099 r_gpuskeletal = false;
7100 switch(vid.renderpath)
7102 case RENDERPATH_GL20:
7103 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
7104 case RENDERPATH_D3D9:
7105 case RENDERPATH_D3D10:
7106 case RENDERPATH_D3D11:
7107 case RENDERPATH_SOFT:
7108 case RENDERPATH_GLES2:
7109 if(v_glslgamma.integer && !vid_gammatables_trivial)
7111 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7113 // build GLSL gamma texture
7114 #define RAMPWIDTH 256
7115 unsigned short ramp[RAMPWIDTH * 3];
7116 unsigned char rampbgr[RAMPWIDTH][4];
7119 r_texture_gammaramps_serial = vid_gammatables_serial;
7121 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7122 for(i = 0; i < RAMPWIDTH; ++i)
7124 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7125 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7126 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7129 if (r_texture_gammaramps)
7131 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7135 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7141 // remove GLSL gamma texture
7144 case RENDERPATH_GL11:
7145 case RENDERPATH_GL13:
7146 case RENDERPATH_GLES1:
7151 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7152 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7158 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7159 if( scenetype != r_currentscenetype ) {
7160 // store the old scenetype
7161 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7162 r_currentscenetype = scenetype;
7163 // move in the new scene
7164 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7173 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7175 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7176 if( scenetype == r_currentscenetype ) {
7177 return &r_refdef.scene;
7179 return &r_scenes_store[ scenetype ];
7183 static int R_SortEntities_Compare(const void *ap, const void *bp)
7185 const entity_render_t *a = *(const entity_render_t **)ap;
7186 const entity_render_t *b = *(const entity_render_t **)bp;
7189 if(a->model < b->model)
7191 if(a->model > b->model)
7195 // TODO possibly calculate the REAL skinnum here first using
7197 if(a->skinnum < b->skinnum)
7199 if(a->skinnum > b->skinnum)
7202 // everything we compared is equal
7205 static void R_SortEntities(void)
7207 // below or equal 2 ents, sorting never gains anything
7208 if(r_refdef.scene.numentities <= 2)
7211 qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7219 int dpsoftrast_test;
7220 extern cvar_t r_shadow_bouncegrid;
7221 void R_RenderView(void)
7223 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7225 rtexture_t *depthtexture;
7226 rtexture_t *colortexture;
7228 dpsoftrast_test = r_test.integer;
7230 if (r_timereport_active)
7231 R_TimeReport("start");
7232 r_textureframe++; // used only by R_GetCurrentTexture
7233 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7235 if(R_CompileShader_CheckStaticParms())
7238 if (!r_drawentities.integer)
7239 r_refdef.scene.numentities = 0;
7240 else if (r_sortentities.integer)
7243 R_AnimCache_ClearCache();
7245 /* adjust for stereo display */
7246 if(R_Stereo_Active())
7248 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);
7249 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7252 if (r_refdef.view.isoverlay)
7254 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7255 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7256 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7257 R_TimeReport("depthclear");
7259 r_refdef.view.showdebug = false;
7261 r_fb.water.enabled = false;
7262 r_fb.water.numwaterplanes = 0;
7264 R_RenderScene(0, NULL, NULL);
7266 r_refdef.view.matrix = originalmatrix;
7272 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7274 r_refdef.view.matrix = originalmatrix;
7278 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7280 if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7281 // in sRGB fallback, behave similar to true sRGB: convert this
7282 // value from linear to sRGB
7283 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7285 R_RenderView_UpdateViewVectors();
7287 R_Shadow_UpdateWorldLightSelection();
7289 R_Bloom_StartFrame();
7291 // apply bloom brightness offset
7292 if(r_fb.bloomtexture[0])
7293 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7295 R_Water_StartFrame();
7297 // now we probably have an fbo to render into
7299 depthtexture = r_fb.depthtexture;
7300 colortexture = r_fb.colortexture;
7303 if (r_timereport_active)
7304 R_TimeReport("viewsetup");
7306 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7308 if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7310 R_ClearScreen(r_refdef.fogenabled);
7311 if (r_timereport_active)
7312 R_TimeReport("viewclear");
7314 r_refdef.view.clear = true;
7316 r_refdef.view.showdebug = true;
7319 if (r_timereport_active)
7320 R_TimeReport("visibility");
7322 R_AnimCache_CacheVisibleEntities();
7323 if (r_timereport_active)
7324 R_TimeReport("animcache");
7326 R_Shadow_UpdateBounceGridTexture();
7327 if (r_timereport_active && r_shadow_bouncegrid.integer)
7328 R_TimeReport("bouncegrid");
7330 r_fb.water.numwaterplanes = 0;
7331 if (r_fb.water.enabled)
7332 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7334 R_RenderScene(fbo, depthtexture, colortexture);
7335 r_fb.water.numwaterplanes = 0;
7337 R_BlendView(fbo, depthtexture, colortexture);
7338 if (r_timereport_active)
7339 R_TimeReport("blendview");
7341 GL_Scissor(0, 0, vid.width, vid.height);
7342 GL_ScissorTest(false);
7344 r_refdef.view.matrix = originalmatrix;
7349 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7351 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7353 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7354 if (r_timereport_active)
7355 R_TimeReport("waterworld");
7358 // don't let sound skip if going slow
7359 if (r_refdef.scene.extraupdate)
7362 R_DrawModelsAddWaterPlanes();
7363 if (r_timereport_active)
7364 R_TimeReport("watermodels");
7366 if (r_fb.water.numwaterplanes)
7368 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7369 if (r_timereport_active)
7370 R_TimeReport("waterscenes");
7374 extern cvar_t cl_locs_show;
7375 static void R_DrawLocs(void);
7376 static void R_DrawEntityBBoxes(void);
7377 static void R_DrawModelDecals(void);
7378 extern cvar_t cl_decals_newsystem;
7379 extern qboolean r_shadow_usingdeferredprepass;
7380 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7382 qboolean shadowmapping = false;
7384 if (r_timereport_active)
7385 R_TimeReport("beginscene");
7387 r_refdef.stats[r_stat_renders]++;
7391 // don't let sound skip if going slow
7392 if (r_refdef.scene.extraupdate)
7395 R_MeshQueue_BeginScene();
7399 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);
7401 if (r_timereport_active)
7402 R_TimeReport("skystartframe");
7404 if (cl.csqc_vidvars.drawworld)
7406 // don't let sound skip if going slow
7407 if (r_refdef.scene.extraupdate)
7410 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7412 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7413 if (r_timereport_active)
7414 R_TimeReport("worldsky");
7417 if (R_DrawBrushModelsSky() && r_timereport_active)
7418 R_TimeReport("bmodelsky");
7420 if (skyrendermasked && skyrenderlater)
7422 // we have to force off the water clipping plane while rendering sky
7423 R_SetupView(false, fbo, depthtexture, colortexture);
7425 R_SetupView(true, fbo, depthtexture, colortexture);
7426 if (r_timereport_active)
7427 R_TimeReport("sky");
7431 R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7432 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7433 R_Shadow_PrepareModelShadows();
7434 if (r_timereport_active)
7435 R_TimeReport("preparelights");
7437 if (R_Shadow_ShadowMappingEnabled())
7438 shadowmapping = true;
7440 if (r_shadow_usingdeferredprepass)
7441 R_Shadow_DrawPrepass();
7443 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7445 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7446 if (r_timereport_active)
7447 R_TimeReport("worlddepth");
7449 if (r_depthfirst.integer >= 2)
7451 R_DrawModelsDepth();
7452 if (r_timereport_active)
7453 R_TimeReport("modeldepth");
7456 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7458 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7459 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7460 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7461 // don't let sound skip if going slow
7462 if (r_refdef.scene.extraupdate)
7466 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7468 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7469 if (r_timereport_active)
7470 R_TimeReport("world");
7473 // don't let sound skip if going slow
7474 if (r_refdef.scene.extraupdate)
7478 if (r_timereport_active)
7479 R_TimeReport("models");
7481 // don't let sound skip if going slow
7482 if (r_refdef.scene.extraupdate)
7485 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7487 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7488 R_DrawModelShadows(fbo, depthtexture, colortexture);
7489 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7490 // don't let sound skip if going slow
7491 if (r_refdef.scene.extraupdate)
7495 if (!r_shadow_usingdeferredprepass)
7497 R_Shadow_DrawLights();
7498 if (r_timereport_active)
7499 R_TimeReport("rtlights");
7502 // don't let sound skip if going slow
7503 if (r_refdef.scene.extraupdate)
7506 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7508 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7509 R_DrawModelShadows(fbo, depthtexture, colortexture);
7510 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7511 // don't let sound skip if going slow
7512 if (r_refdef.scene.extraupdate)
7516 if (cl.csqc_vidvars.drawworld)
7518 if (cl_decals_newsystem.integer)
7520 R_DrawModelDecals();
7521 if (r_timereport_active)
7522 R_TimeReport("modeldecals");
7527 if (r_timereport_active)
7528 R_TimeReport("decals");
7532 if (r_timereport_active)
7533 R_TimeReport("particles");
7536 if (r_timereport_active)
7537 R_TimeReport("explosions");
7539 R_DrawLightningBeams();
7540 if (r_timereport_active)
7541 R_TimeReport("lightning");
7545 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7547 if (r_refdef.view.showdebug)
7549 if (cl_locs_show.integer)
7552 if (r_timereport_active)
7553 R_TimeReport("showlocs");
7556 if (r_drawportals.integer)
7559 if (r_timereport_active)
7560 R_TimeReport("portals");
7563 if (r_showbboxes.value > 0)
7565 R_DrawEntityBBoxes();
7566 if (r_timereport_active)
7567 R_TimeReport("bboxes");
7571 if (r_transparent.integer)
7573 R_MeshQueue_RenderTransparent();
7574 if (r_timereport_active)
7575 R_TimeReport("drawtrans");
7578 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))
7580 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7581 if (r_timereport_active)
7582 R_TimeReport("worlddebug");
7583 R_DrawModelsDebug();
7584 if (r_timereport_active)
7585 R_TimeReport("modeldebug");
7588 if (cl.csqc_vidvars.drawworld)
7590 R_Shadow_DrawCoronas();
7591 if (r_timereport_active)
7592 R_TimeReport("coronas");
7597 GL_DepthTest(false);
7598 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7599 GL_Color(1, 1, 1, 1);
7600 qglBegin(GL_POLYGON);
7601 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7602 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7603 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7604 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7606 qglBegin(GL_POLYGON);
7607 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]);
7608 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]);
7609 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]);
7610 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]);
7612 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7616 // don't let sound skip if going slow
7617 if (r_refdef.scene.extraupdate)
7621 static const unsigned short bboxelements[36] =
7631 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7634 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7636 RSurf_ActiveWorldEntity();
7638 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7639 GL_DepthMask(false);
7640 GL_DepthRange(0, 1);
7641 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7642 // R_Mesh_ResetTextureState();
7644 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7645 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7646 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7647 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7648 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7649 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7650 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7651 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7652 R_FillColors(color4f, 8, cr, cg, cb, ca);
7653 if (r_refdef.fogenabled)
7655 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7657 f1 = RSurf_FogVertex(v);
7659 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7660 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7661 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7664 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7665 R_Mesh_ResetTextureState();
7666 R_SetupShader_Generic_NoTexture(false, false);
7667 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7670 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7672 prvm_prog_t *prog = SVVM_prog;
7675 prvm_edict_t *edict;
7677 // this function draws bounding boxes of server entities
7681 GL_CullFace(GL_NONE);
7682 R_SetupShader_Generic_NoTexture(false, false);
7684 for (i = 0;i < numsurfaces;i++)
7686 edict = PRVM_EDICT_NUM(surfacelist[i]);
7687 switch ((int)PRVM_serveredictfloat(edict, solid))
7689 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7690 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7691 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7692 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7693 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7694 case SOLID_CORPSE: Vector4Set(color, 1, 0.5, 0, 0.05);break;
7695 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7697 color[3] *= r_showbboxes.value;
7698 color[3] = bound(0, color[3], 1);
7699 GL_DepthTest(!r_showdisabledepthtest.integer);
7700 GL_CullFace(r_refdef.view.cullface_front);
7701 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7705 static void R_DrawEntityBBoxes(void)
7708 prvm_edict_t *edict;
7710 prvm_prog_t *prog = SVVM_prog;
7712 // this function draws bounding boxes of server entities
7716 for (i = 0;i < prog->num_edicts;i++)
7718 edict = PRVM_EDICT_NUM(i);
7719 if (edict->priv.server->free)
7721 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7722 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7724 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7726 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7727 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7731 static const int nomodelelement3i[24] =
7743 static const unsigned short nomodelelement3s[24] =
7755 static const float nomodelvertex3f[6*3] =
7765 static const float nomodelcolor4f[6*4] =
7767 0.0f, 0.0f, 0.5f, 1.0f,
7768 0.0f, 0.0f, 0.5f, 1.0f,
7769 0.0f, 0.5f, 0.0f, 1.0f,
7770 0.0f, 0.5f, 0.0f, 1.0f,
7771 0.5f, 0.0f, 0.0f, 1.0f,
7772 0.5f, 0.0f, 0.0f, 1.0f
7775 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7781 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);
7783 // this is only called once per entity so numsurfaces is always 1, and
7784 // surfacelist is always {0}, so this code does not handle batches
7786 if (rsurface.ent_flags & RENDER_ADDITIVE)
7788 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7789 GL_DepthMask(false);
7791 else if (rsurface.colormod[3] < 1)
7793 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7794 GL_DepthMask(false);
7798 GL_BlendFunc(GL_ONE, GL_ZERO);
7801 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7802 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7803 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7804 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7805 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7806 for (i = 0, c = color4f;i < 6;i++, c += 4)
7808 c[0] *= rsurface.colormod[0];
7809 c[1] *= rsurface.colormod[1];
7810 c[2] *= rsurface.colormod[2];
7811 c[3] *= rsurface.colormod[3];
7813 if (r_refdef.fogenabled)
7815 for (i = 0, c = color4f;i < 6;i++, c += 4)
7817 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7819 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7820 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7821 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7824 // R_Mesh_ResetTextureState();
7825 R_SetupShader_Generic_NoTexture(false, false);
7826 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7827 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7830 void R_DrawNoModel(entity_render_t *ent)
7833 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7834 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7835 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7837 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7840 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7842 vec3_t right1, right2, diff, normal;
7844 VectorSubtract (org2, org1, normal);
7846 // calculate 'right' vector for start
7847 VectorSubtract (r_refdef.view.origin, org1, diff);
7848 CrossProduct (normal, diff, right1);
7849 VectorNormalize (right1);
7851 // calculate 'right' vector for end
7852 VectorSubtract (r_refdef.view.origin, org2, diff);
7853 CrossProduct (normal, diff, right2);
7854 VectorNormalize (right2);
7856 vert[ 0] = org1[0] + width * right1[0];
7857 vert[ 1] = org1[1] + width * right1[1];
7858 vert[ 2] = org1[2] + width * right1[2];
7859 vert[ 3] = org1[0] - width * right1[0];
7860 vert[ 4] = org1[1] - width * right1[1];
7861 vert[ 5] = org1[2] - width * right1[2];
7862 vert[ 6] = org2[0] - width * right2[0];
7863 vert[ 7] = org2[1] - width * right2[1];
7864 vert[ 8] = org2[2] - width * right2[2];
7865 vert[ 9] = org2[0] + width * right2[0];
7866 vert[10] = org2[1] + width * right2[1];
7867 vert[11] = org2[2] + width * right2[2];
7870 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)
7872 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7873 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7874 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7875 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7876 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7877 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7878 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7879 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7880 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7881 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7882 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7883 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7886 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7891 VectorSet(v, x, y, z);
7892 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7893 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7895 if (i == mesh->numvertices)
7897 if (mesh->numvertices < mesh->maxvertices)
7899 VectorCopy(v, vertex3f);
7900 mesh->numvertices++;
7902 return mesh->numvertices;
7908 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7912 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7913 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7914 e = mesh->element3i + mesh->numtriangles * 3;
7915 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7917 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7918 if (mesh->numtriangles < mesh->maxtriangles)
7923 mesh->numtriangles++;
7925 element[1] = element[2];
7929 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7933 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7934 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7935 e = mesh->element3i + mesh->numtriangles * 3;
7936 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7938 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7939 if (mesh->numtriangles < mesh->maxtriangles)
7944 mesh->numtriangles++;
7946 element[1] = element[2];
7950 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7951 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7953 int planenum, planenum2;
7956 mplane_t *plane, *plane2;
7958 double temppoints[2][256*3];
7959 // figure out how large a bounding box we need to properly compute this brush
7961 for (w = 0;w < numplanes;w++)
7962 maxdist = max(maxdist, fabs(planes[w].dist));
7963 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7964 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7965 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7969 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7970 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7972 if (planenum2 == planenum)
7974 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);
7977 if (tempnumpoints < 3)
7979 // generate elements forming a triangle fan for this polygon
7980 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7984 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)
7986 texturelayer_t *layer;
7987 layer = t->currentlayers + t->currentnumlayers++;
7989 layer->depthmask = depthmask;
7990 layer->blendfunc1 = blendfunc1;
7991 layer->blendfunc2 = blendfunc2;
7992 layer->texture = texture;
7993 layer->texmatrix = *matrix;
7994 layer->color[0] = r;
7995 layer->color[1] = g;
7996 layer->color[2] = b;
7997 layer->color[3] = a;
8000 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
8002 if(parms[0] == 0 && parms[1] == 0)
8004 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8005 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
8010 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8013 index = parms[2] + rsurface.shadertime * parms[3];
8014 index -= floor(index);
8015 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
8018 case Q3WAVEFUNC_NONE:
8019 case Q3WAVEFUNC_NOISE:
8020 case Q3WAVEFUNC_COUNT:
8023 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8024 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8025 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8026 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8027 case Q3WAVEFUNC_TRIANGLE:
8029 f = index - floor(index);
8042 f = parms[0] + parms[1] * f;
8043 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8044 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
8048 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8055 matrix4x4_t matrix, temp;
8056 // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
8057 // it's better to have one huge fixup every 9 hours than gradual
8058 // degradation over time which looks consistently bad after many hours.
8060 // tcmod scroll in particular suffers from this degradation which can't be
8061 // effectively worked around even with floor() tricks because we don't
8062 // know if tcmod scroll is the last tcmod being applied, and for clampmap
8063 // a workaround involving floor() would be incorrect anyway...
8064 shadertime = rsurface.shadertime;
8065 if (shadertime >= 32768.0f)
8066 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
8067 switch(tcmod->tcmod)
8071 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8072 matrix = r_waterscrollmatrix;
8074 matrix = identitymatrix;
8076 case Q3TCMOD_ENTITYTRANSLATE:
8077 // this is used in Q3 to allow the gamecode to control texcoord
8078 // scrolling on the entity, which is not supported in darkplaces yet.
8079 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8081 case Q3TCMOD_ROTATE:
8082 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8083 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
8084 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8087 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8089 case Q3TCMOD_SCROLL:
8090 // this particular tcmod is a "bug for bug" compatible one with regards to
8091 // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
8092 // specifically did the wrapping and so we must mimic that...
8093 offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
8094 offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
8095 Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
8097 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8098 w = (int) tcmod->parms[0];
8099 h = (int) tcmod->parms[1];
8100 f = rsurface.shadertime / (tcmod->parms[2] * w * h);
8102 idx = (int) floor(f * w * h);
8103 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8105 case Q3TCMOD_STRETCH:
8106 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8107 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8109 case Q3TCMOD_TRANSFORM:
8110 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
8111 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
8112 VectorSet(tcmat + 6, 0 , 0 , 1);
8113 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
8114 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8116 case Q3TCMOD_TURBULENT:
8117 // this is handled in the RSurf_PrepareVertices function
8118 matrix = identitymatrix;
8122 Matrix4x4_Concat(texmatrix, &matrix, &temp);
8125 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8127 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8128 char name[MAX_QPATH];
8129 skinframe_t *skinframe;
8130 unsigned char pixels[296*194];
8131 strlcpy(cache->name, skinname, sizeof(cache->name));
8132 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8133 if (developer_loading.integer)
8134 Con_Printf("loading %s\n", name);
8135 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8136 if (!skinframe || !skinframe->base)
8139 fs_offset_t filesize;
8141 f = FS_LoadFile(name, tempmempool, true, &filesize);
8144 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8145 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8149 cache->skinframe = skinframe;
8152 texture_t *R_GetCurrentTexture(texture_t *t)
8155 const entity_render_t *ent = rsurface.entity;
8156 dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8157 q3shaderinfo_layer_tcmod_t *tcmod;
8159 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8160 return t->currentframe;
8161 t->update_lastrenderframe = r_textureframe;
8162 t->update_lastrenderentity = (void *)ent;
8164 if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8165 t->camera_entity = ent->entitynumber;
8167 t->camera_entity = 0;
8169 // switch to an alternate material if this is a q1bsp animated material
8171 texture_t *texture = t;
8172 int s = rsurface.ent_skinnum;
8173 if ((unsigned int)s >= (unsigned int)model->numskins)
8175 if (model->skinscenes)
8177 if (model->skinscenes[s].framecount > 1)
8178 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8180 s = model->skinscenes[s].firstframe;
8183 t = t + s * model->num_surfaces;
8186 // use an alternate animation if the entity's frame is not 0,
8187 // and only if the texture has an alternate animation
8188 if (t->animated == 2) // q2bsp
8189 t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]];
8190 else if (rsurface.ent_alttextures && t->anim_total[1])
8191 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8193 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8195 texture->currentframe = t;
8198 // update currentskinframe to be a qw skin or animation frame
8199 if (rsurface.ent_qwskin >= 0)
8201 i = rsurface.ent_qwskin;
8202 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8204 r_qwskincache_size = cl.maxclients;
8206 Mem_Free(r_qwskincache);
8207 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8209 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8210 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8211 t->currentskinframe = r_qwskincache[i].skinframe;
8212 if (t->currentskinframe == NULL)
8213 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8215 else if (t->numskinframes >= 2)
8216 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8217 if (t->backgroundnumskinframes >= 2)
8218 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
8220 t->currentmaterialflags = t->basematerialflags;
8221 t->currentalpha = rsurface.colormod[3] * t->basealpha;
8222 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8223 t->currentalpha *= r_wateralpha.value;
8224 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8225 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8226 if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8227 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8228 if (!(rsurface.ent_flags & RENDER_LIGHT))
8229 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8230 else if (FAKELIGHT_ENABLED)
8232 // no modellight if using fakelight for the map
8234 else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8236 // pick a model lighting mode
8237 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8238 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8240 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8242 if (rsurface.ent_flags & RENDER_ADDITIVE)
8243 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8244 else if (t->currentalpha < 1)
8245 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8246 // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8247 if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8248 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8249 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8250 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8251 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8252 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8253 if (t->backgroundnumskinframes)
8254 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8255 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8257 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8258 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8261 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8262 if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8264 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8265 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8267 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8268 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8270 // there is no tcmod
8271 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8273 t->currenttexmatrix = r_waterscrollmatrix;
8274 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8276 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8278 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8279 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8282 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8283 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8284 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8285 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8287 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8288 if (t->currentskinframe->qpixels)
8289 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8290 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8291 if (!t->basetexture)
8292 t->basetexture = r_texture_notexture;
8293 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8294 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8295 t->nmaptexture = t->currentskinframe->nmap;
8296 if (!t->nmaptexture)
8297 t->nmaptexture = r_texture_blanknormalmap;
8298 t->glosstexture = r_texture_black;
8299 t->glowtexture = t->currentskinframe->glow;
8300 t->fogtexture = t->currentskinframe->fog;
8301 t->reflectmasktexture = t->currentskinframe->reflect;
8302 if (t->backgroundnumskinframes)
8304 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8305 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8306 t->backgroundglosstexture = r_texture_black;
8307 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8308 if (!t->backgroundnmaptexture)
8309 t->backgroundnmaptexture = r_texture_blanknormalmap;
8310 // make sure that if glow is going to be used, both textures are not NULL
8311 if (!t->backgroundglowtexture && t->glowtexture)
8312 t->backgroundglowtexture = r_texture_black;
8313 if (!t->glowtexture && t->backgroundglowtexture)
8314 t->glowtexture = r_texture_black;
8318 t->backgroundbasetexture = r_texture_white;
8319 t->backgroundnmaptexture = r_texture_blanknormalmap;
8320 t->backgroundglosstexture = r_texture_black;
8321 t->backgroundglowtexture = NULL;
8323 t->specularpower = r_shadow_glossexponent.value;
8324 // TODO: store reference values for these in the texture?
8325 t->specularscale = 0;
8326 if (r_shadow_gloss.integer > 0)
8328 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8330 if (r_shadow_glossintensity.value > 0)
8332 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8333 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8334 t->specularscale = r_shadow_glossintensity.value;
8337 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8339 t->glosstexture = r_texture_white;
8340 t->backgroundglosstexture = r_texture_white;
8341 t->specularscale = r_shadow_gloss2intensity.value;
8342 t->specularpower = r_shadow_gloss2exponent.value;
8345 t->specularscale *= t->specularscalemod;
8346 t->specularpower *= t->specularpowermod;
8347 t->rtlightambient = 0;
8349 // lightmaps mode looks bad with dlights using actual texturing, so turn
8350 // off the colormap and glossmap, but leave the normalmap on as it still
8351 // accurately represents the shading involved
8352 if (gl_lightmaps.integer)
8354 t->basetexture = r_texture_grey128;
8355 t->pantstexture = r_texture_black;
8356 t->shirttexture = r_texture_black;
8357 if (gl_lightmaps.integer < 2)
8358 t->nmaptexture = r_texture_blanknormalmap;
8359 t->glosstexture = r_texture_black;
8360 t->glowtexture = NULL;
8361 t->fogtexture = NULL;
8362 t->reflectmasktexture = NULL;
8363 t->backgroundbasetexture = NULL;
8364 if (gl_lightmaps.integer < 2)
8365 t->backgroundnmaptexture = r_texture_blanknormalmap;
8366 t->backgroundglosstexture = r_texture_black;
8367 t->backgroundglowtexture = NULL;
8368 t->specularscale = 0;
8369 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8372 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8373 VectorClear(t->dlightcolor);
8374 t->currentnumlayers = 0;
8375 if (t->currentmaterialflags & MATERIALFLAG_WALL)
8377 int blendfunc1, blendfunc2;
8379 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8381 blendfunc1 = GL_SRC_ALPHA;
8382 blendfunc2 = GL_ONE;
8384 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8386 blendfunc1 = GL_SRC_ALPHA;
8387 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8389 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8391 blendfunc1 = t->customblendfunc[0];
8392 blendfunc2 = t->customblendfunc[1];
8396 blendfunc1 = GL_ONE;
8397 blendfunc2 = GL_ZERO;
8399 // don't colormod evilblend textures
8400 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8401 VectorSet(t->lightmapcolor, 1, 1, 1);
8402 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8403 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8405 // fullbright is not affected by r_refdef.lightmapintensity
8406 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]);
8407 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8408 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]);
8409 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8410 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]);
8414 vec3_t ambientcolor;
8416 // set the color tint used for lights affecting this surface
8417 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8419 // q3bsp has no lightmap updates, so the lightstylevalue that
8420 // would normally be baked into the lightmap must be
8421 // applied to the color
8422 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8423 if (model->type == mod_brushq3)
8424 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8425 colorscale *= r_refdef.lightmapintensity;
8426 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8427 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8428 // basic lit geometry
8429 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]);
8430 // add pants/shirt if needed
8431 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8432 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]);
8433 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8434 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]);
8435 // now add ambient passes if needed
8436 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8438 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]);
8439 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8440 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]);
8441 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8442 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]);
8445 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8446 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]);
8447 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8449 // if this is opaque use alpha blend which will darken the earlier
8452 // if this is an alpha blended material, all the earlier passes
8453 // were darkened by fog already, so we only need to add the fog
8454 // color ontop through the fog mask texture
8456 // if this is an additive blended material, all the earlier passes
8457 // were darkened by fog already, and we should not add fog color
8458 // (because the background was not darkened, there is no fog color
8459 // that was lost behind it).
8460 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]);
8467 rsurfacestate_t rsurface;
8469 void RSurf_ActiveWorldEntity(void)
8471 dp_model_t *model = r_refdef.scene.worldmodel;
8472 //if (rsurface.entity == r_refdef.scene.worldentity)
8474 rsurface.entity = r_refdef.scene.worldentity;
8475 rsurface.skeleton = NULL;
8476 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8477 rsurface.ent_skinnum = 0;
8478 rsurface.ent_qwskin = -1;
8479 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8480 rsurface.shadertime = r_refdef.scene.time;
8481 rsurface.matrix = identitymatrix;
8482 rsurface.inversematrix = identitymatrix;
8483 rsurface.matrixscale = 1;
8484 rsurface.inversematrixscale = 1;
8485 R_EntityMatrix(&identitymatrix);
8486 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8487 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8488 rsurface.fograngerecip = r_refdef.fograngerecip;
8489 rsurface.fogheightfade = r_refdef.fogheightfade;
8490 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8491 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8492 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8493 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8494 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8495 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8496 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8497 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8498 rsurface.colormod[3] = 1;
8499 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);
8500 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8501 rsurface.frameblend[0].lerp = 1;
8502 rsurface.ent_alttextures = false;
8503 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8504 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8505 rsurface.entityskeletaltransform3x4 = NULL;
8506 rsurface.entityskeletaltransform3x4buffer = NULL;
8507 rsurface.entityskeletaltransform3x4offset = 0;
8508 rsurface.entityskeletaltransform3x4size = 0;;
8509 rsurface.entityskeletalnumtransforms = 0;
8510 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8511 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8512 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8513 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8514 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8515 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8516 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8517 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8518 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8519 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8520 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8521 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8522 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8523 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8524 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8525 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8526 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8527 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8528 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8529 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8530 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8531 rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8532 rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8533 rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8534 rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8535 rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8536 rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8537 rsurface.modelelement3i = model->surfmesh.data_element3i;
8538 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8539 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8540 rsurface.modelelement3s = model->surfmesh.data_element3s;
8541 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8542 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8543 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8544 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8545 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8546 rsurface.modelsurfaces = model->data_surfaces;
8547 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8548 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8549 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8550 rsurface.modelgeneratedvertex = false;
8551 rsurface.batchgeneratedvertex = false;
8552 rsurface.batchfirstvertex = 0;
8553 rsurface.batchnumvertices = 0;
8554 rsurface.batchfirsttriangle = 0;
8555 rsurface.batchnumtriangles = 0;
8556 rsurface.batchvertex3f = NULL;
8557 rsurface.batchvertex3f_vertexbuffer = NULL;
8558 rsurface.batchvertex3f_bufferoffset = 0;
8559 rsurface.batchsvector3f = NULL;
8560 rsurface.batchsvector3f_vertexbuffer = NULL;
8561 rsurface.batchsvector3f_bufferoffset = 0;
8562 rsurface.batchtvector3f = NULL;
8563 rsurface.batchtvector3f_vertexbuffer = NULL;
8564 rsurface.batchtvector3f_bufferoffset = 0;
8565 rsurface.batchnormal3f = NULL;
8566 rsurface.batchnormal3f_vertexbuffer = NULL;
8567 rsurface.batchnormal3f_bufferoffset = 0;
8568 rsurface.batchlightmapcolor4f = NULL;
8569 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8570 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8571 rsurface.batchtexcoordtexture2f = NULL;
8572 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8573 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8574 rsurface.batchtexcoordlightmap2f = NULL;
8575 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8576 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8577 rsurface.batchskeletalindex4ub = NULL;
8578 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8579 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8580 rsurface.batchskeletalweight4ub = NULL;
8581 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8582 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8583 rsurface.batchvertexmesh = NULL;
8584 rsurface.batchvertexmesh_vertexbuffer = NULL;
8585 rsurface.batchvertexmesh_bufferoffset = 0;
8586 rsurface.batchelement3i = NULL;
8587 rsurface.batchelement3i_indexbuffer = NULL;
8588 rsurface.batchelement3i_bufferoffset = 0;
8589 rsurface.batchelement3s = NULL;
8590 rsurface.batchelement3s_indexbuffer = NULL;
8591 rsurface.batchelement3s_bufferoffset = 0;
8592 rsurface.passcolor4f = NULL;
8593 rsurface.passcolor4f_vertexbuffer = NULL;
8594 rsurface.passcolor4f_bufferoffset = 0;
8595 rsurface.forcecurrenttextureupdate = false;
8598 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8600 dp_model_t *model = ent->model;
8601 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8603 rsurface.entity = (entity_render_t *)ent;
8604 rsurface.skeleton = ent->skeleton;
8605 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8606 rsurface.ent_skinnum = ent->skinnum;
8607 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;
8608 rsurface.ent_flags = ent->flags;
8609 rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8610 rsurface.matrix = ent->matrix;
8611 rsurface.inversematrix = ent->inversematrix;
8612 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8613 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8614 R_EntityMatrix(&rsurface.matrix);
8615 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8616 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8617 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8618 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8619 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8620 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8621 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8622 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8623 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8624 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8625 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8626 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8627 rsurface.colormod[3] = ent->alpha;
8628 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8629 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8630 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8631 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8632 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8633 if (ent->model->brush.submodel && !prepass)
8635 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8636 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8638 // if the animcache code decided it should use the shader path, skip the deform step
8639 rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8640 rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8641 rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8642 rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8643 rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8644 if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8646 if (ent->animcache_vertex3f)
8648 r_refdef.stats[r_stat_batch_entitycache_count]++;
8649 r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8650 r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8651 r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8652 rsurface.modelvertex3f = ent->animcache_vertex3f;
8653 rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8654 rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8655 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8656 rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8657 rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8658 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8659 rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8660 rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8661 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8662 rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8663 rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8664 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8665 rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8666 rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8668 else if (wanttangents)
8670 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8671 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8672 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8673 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8674 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8675 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8676 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8677 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8678 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8679 rsurface.modelvertexmesh = NULL;
8680 rsurface.modelvertexmesh_vertexbuffer = NULL;
8681 rsurface.modelvertexmesh_bufferoffset = 0;
8682 rsurface.modelvertex3f_vertexbuffer = NULL;
8683 rsurface.modelvertex3f_bufferoffset = 0;
8684 rsurface.modelvertex3f_vertexbuffer = 0;
8685 rsurface.modelvertex3f_bufferoffset = 0;
8686 rsurface.modelsvector3f_vertexbuffer = 0;
8687 rsurface.modelsvector3f_bufferoffset = 0;
8688 rsurface.modeltvector3f_vertexbuffer = 0;
8689 rsurface.modeltvector3f_bufferoffset = 0;
8690 rsurface.modelnormal3f_vertexbuffer = 0;
8691 rsurface.modelnormal3f_bufferoffset = 0;
8693 else if (wantnormals)
8695 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8696 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8697 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8698 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8699 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8700 rsurface.modelsvector3f = NULL;
8701 rsurface.modeltvector3f = NULL;
8702 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8703 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8704 rsurface.modelvertexmesh = NULL;
8705 rsurface.modelvertexmesh_vertexbuffer = NULL;
8706 rsurface.modelvertexmesh_bufferoffset = 0;
8707 rsurface.modelvertex3f_vertexbuffer = NULL;
8708 rsurface.modelvertex3f_bufferoffset = 0;
8709 rsurface.modelvertex3f_vertexbuffer = 0;
8710 rsurface.modelvertex3f_bufferoffset = 0;
8711 rsurface.modelsvector3f_vertexbuffer = 0;
8712 rsurface.modelsvector3f_bufferoffset = 0;
8713 rsurface.modeltvector3f_vertexbuffer = 0;
8714 rsurface.modeltvector3f_bufferoffset = 0;
8715 rsurface.modelnormal3f_vertexbuffer = 0;
8716 rsurface.modelnormal3f_bufferoffset = 0;
8720 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8721 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8722 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8723 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8724 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8725 rsurface.modelsvector3f = NULL;
8726 rsurface.modeltvector3f = NULL;
8727 rsurface.modelnormal3f = NULL;
8728 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8729 rsurface.modelvertexmesh = NULL;
8730 rsurface.modelvertexmesh_vertexbuffer = NULL;
8731 rsurface.modelvertexmesh_bufferoffset = 0;
8732 rsurface.modelvertex3f_vertexbuffer = NULL;
8733 rsurface.modelvertex3f_bufferoffset = 0;
8734 rsurface.modelvertex3f_vertexbuffer = 0;
8735 rsurface.modelvertex3f_bufferoffset = 0;
8736 rsurface.modelsvector3f_vertexbuffer = 0;
8737 rsurface.modelsvector3f_bufferoffset = 0;
8738 rsurface.modeltvector3f_vertexbuffer = 0;
8739 rsurface.modeltvector3f_bufferoffset = 0;
8740 rsurface.modelnormal3f_vertexbuffer = 0;
8741 rsurface.modelnormal3f_bufferoffset = 0;
8743 rsurface.modelgeneratedvertex = true;
8747 if (rsurface.entityskeletaltransform3x4)
8749 r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8750 r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8751 r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8752 r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8756 r_refdef.stats[r_stat_batch_entitystatic_count]++;
8757 r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8758 r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8759 r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8761 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8762 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8763 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8764 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8765 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8766 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8767 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8768 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8769 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8770 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8771 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8772 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8773 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8774 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8775 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8776 rsurface.modelgeneratedvertex = false;
8778 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8779 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8780 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8781 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8782 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8783 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8784 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8785 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8786 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8787 rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8788 rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8789 rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8790 rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8791 rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8792 rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8793 rsurface.modelelement3i = model->surfmesh.data_element3i;
8794 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8795 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8796 rsurface.modelelement3s = model->surfmesh.data_element3s;
8797 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8798 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8799 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8800 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8801 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8802 rsurface.modelsurfaces = model->data_surfaces;
8803 rsurface.batchgeneratedvertex = false;
8804 rsurface.batchfirstvertex = 0;
8805 rsurface.batchnumvertices = 0;
8806 rsurface.batchfirsttriangle = 0;
8807 rsurface.batchnumtriangles = 0;
8808 rsurface.batchvertex3f = NULL;
8809 rsurface.batchvertex3f_vertexbuffer = NULL;
8810 rsurface.batchvertex3f_bufferoffset = 0;
8811 rsurface.batchsvector3f = NULL;
8812 rsurface.batchsvector3f_vertexbuffer = NULL;
8813 rsurface.batchsvector3f_bufferoffset = 0;
8814 rsurface.batchtvector3f = NULL;
8815 rsurface.batchtvector3f_vertexbuffer = NULL;
8816 rsurface.batchtvector3f_bufferoffset = 0;
8817 rsurface.batchnormal3f = NULL;
8818 rsurface.batchnormal3f_vertexbuffer = NULL;
8819 rsurface.batchnormal3f_bufferoffset = 0;
8820 rsurface.batchlightmapcolor4f = NULL;
8821 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8822 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8823 rsurface.batchtexcoordtexture2f = NULL;
8824 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8825 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8826 rsurface.batchtexcoordlightmap2f = NULL;
8827 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8828 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8829 rsurface.batchskeletalindex4ub = NULL;
8830 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8831 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8832 rsurface.batchskeletalweight4ub = NULL;
8833 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8834 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8835 rsurface.batchvertexmesh = NULL;
8836 rsurface.batchvertexmesh_vertexbuffer = NULL;
8837 rsurface.batchvertexmesh_bufferoffset = 0;
8838 rsurface.batchelement3i = NULL;
8839 rsurface.batchelement3i_indexbuffer = NULL;
8840 rsurface.batchelement3i_bufferoffset = 0;
8841 rsurface.batchelement3s = NULL;
8842 rsurface.batchelement3s_indexbuffer = NULL;
8843 rsurface.batchelement3s_bufferoffset = 0;
8844 rsurface.passcolor4f = NULL;
8845 rsurface.passcolor4f_vertexbuffer = NULL;
8846 rsurface.passcolor4f_bufferoffset = 0;
8847 rsurface.forcecurrenttextureupdate = false;
8850 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)
8852 rsurface.entity = r_refdef.scene.worldentity;
8853 rsurface.skeleton = NULL;
8854 rsurface.ent_skinnum = 0;
8855 rsurface.ent_qwskin = -1;
8856 rsurface.ent_flags = entflags;
8857 rsurface.shadertime = r_refdef.scene.time - shadertime;
8858 rsurface.modelnumvertices = numvertices;
8859 rsurface.modelnumtriangles = numtriangles;
8860 rsurface.matrix = *matrix;
8861 rsurface.inversematrix = *inversematrix;
8862 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8863 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8864 R_EntityMatrix(&rsurface.matrix);
8865 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8866 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8867 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8868 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8869 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8870 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8871 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8872 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8873 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8874 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8875 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8876 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8877 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);
8878 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8879 rsurface.frameblend[0].lerp = 1;
8880 rsurface.ent_alttextures = false;
8881 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8882 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8883 rsurface.entityskeletaltransform3x4 = NULL;
8884 rsurface.entityskeletaltransform3x4buffer = NULL;
8885 rsurface.entityskeletaltransform3x4offset = 0;
8886 rsurface.entityskeletaltransform3x4size = 0;
8887 rsurface.entityskeletalnumtransforms = 0;
8888 r_refdef.stats[r_stat_batch_entitycustom_count]++;
8889 r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8890 r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8891 r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8894 rsurface.modelvertex3f = (float *)vertex3f;
8895 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8896 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8897 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8899 else if (wantnormals)
8901 rsurface.modelvertex3f = (float *)vertex3f;
8902 rsurface.modelsvector3f = NULL;
8903 rsurface.modeltvector3f = NULL;
8904 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8908 rsurface.modelvertex3f = (float *)vertex3f;
8909 rsurface.modelsvector3f = NULL;
8910 rsurface.modeltvector3f = NULL;
8911 rsurface.modelnormal3f = NULL;
8913 rsurface.modelvertexmesh = NULL;
8914 rsurface.modelvertexmesh_vertexbuffer = NULL;
8915 rsurface.modelvertexmesh_bufferoffset = 0;
8916 rsurface.modelvertex3f_vertexbuffer = 0;
8917 rsurface.modelvertex3f_bufferoffset = 0;
8918 rsurface.modelsvector3f_vertexbuffer = 0;
8919 rsurface.modelsvector3f_bufferoffset = 0;
8920 rsurface.modeltvector3f_vertexbuffer = 0;
8921 rsurface.modeltvector3f_bufferoffset = 0;
8922 rsurface.modelnormal3f_vertexbuffer = 0;
8923 rsurface.modelnormal3f_bufferoffset = 0;
8924 rsurface.modelgeneratedvertex = true;
8925 rsurface.modellightmapcolor4f = (float *)color4f;
8926 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8927 rsurface.modellightmapcolor4f_bufferoffset = 0;
8928 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8929 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8930 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8931 rsurface.modeltexcoordlightmap2f = NULL;
8932 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8933 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8934 rsurface.modelskeletalindex4ub = NULL;
8935 rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8936 rsurface.modelskeletalindex4ub_bufferoffset = 0;
8937 rsurface.modelskeletalweight4ub = NULL;
8938 rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8939 rsurface.modelskeletalweight4ub_bufferoffset = 0;
8940 rsurface.modelelement3i = (int *)element3i;
8941 rsurface.modelelement3i_indexbuffer = NULL;
8942 rsurface.modelelement3i_bufferoffset = 0;
8943 rsurface.modelelement3s = (unsigned short *)element3s;
8944 rsurface.modelelement3s_indexbuffer = NULL;
8945 rsurface.modelelement3s_bufferoffset = 0;
8946 rsurface.modellightmapoffsets = NULL;
8947 rsurface.modelsurfaces = NULL;
8948 rsurface.batchgeneratedvertex = false;
8949 rsurface.batchfirstvertex = 0;
8950 rsurface.batchnumvertices = 0;
8951 rsurface.batchfirsttriangle = 0;
8952 rsurface.batchnumtriangles = 0;
8953 rsurface.batchvertex3f = NULL;
8954 rsurface.batchvertex3f_vertexbuffer = NULL;
8955 rsurface.batchvertex3f_bufferoffset = 0;
8956 rsurface.batchsvector3f = NULL;
8957 rsurface.batchsvector3f_vertexbuffer = NULL;
8958 rsurface.batchsvector3f_bufferoffset = 0;
8959 rsurface.batchtvector3f = NULL;
8960 rsurface.batchtvector3f_vertexbuffer = NULL;
8961 rsurface.batchtvector3f_bufferoffset = 0;
8962 rsurface.batchnormal3f = NULL;
8963 rsurface.batchnormal3f_vertexbuffer = NULL;
8964 rsurface.batchnormal3f_bufferoffset = 0;
8965 rsurface.batchlightmapcolor4f = NULL;
8966 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8967 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8968 rsurface.batchtexcoordtexture2f = NULL;
8969 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8970 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8971 rsurface.batchtexcoordlightmap2f = NULL;
8972 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8973 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8974 rsurface.batchskeletalindex4ub = NULL;
8975 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8976 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8977 rsurface.batchskeletalweight4ub = NULL;
8978 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8979 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8980 rsurface.batchvertexmesh = NULL;
8981 rsurface.batchvertexmesh_vertexbuffer = NULL;
8982 rsurface.batchvertexmesh_bufferoffset = 0;
8983 rsurface.batchelement3i = NULL;
8984 rsurface.batchelement3i_indexbuffer = NULL;
8985 rsurface.batchelement3i_bufferoffset = 0;
8986 rsurface.batchelement3s = NULL;
8987 rsurface.batchelement3s_indexbuffer = NULL;
8988 rsurface.batchelement3s_bufferoffset = 0;
8989 rsurface.passcolor4f = NULL;
8990 rsurface.passcolor4f_vertexbuffer = NULL;
8991 rsurface.passcolor4f_bufferoffset = 0;
8992 rsurface.forcecurrenttextureupdate = true;
8994 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8996 if ((wantnormals || wanttangents) && !normal3f)
8998 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8999 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9001 if (wanttangents && !svector3f)
9003 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9004 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9005 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
9010 float RSurf_FogPoint(const float *v)
9012 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9013 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9014 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9015 float FogHeightFade = r_refdef.fogheightfade;
9017 unsigned int fogmasktableindex;
9018 if (r_refdef.fogplaneviewabove)
9019 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9021 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9022 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9023 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9026 float RSurf_FogVertex(const float *v)
9028 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9029 float FogPlaneViewDist = rsurface.fogplaneviewdist;
9030 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9031 float FogHeightFade = rsurface.fogheightfade;
9033 unsigned int fogmasktableindex;
9034 if (r_refdef.fogplaneviewabove)
9035 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9037 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9038 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9039 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9042 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
9045 for (i = 0;i < numelements;i++)
9046 outelement3i[i] = inelement3i[i] + adjust;
9049 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9050 extern cvar_t gl_vbo;
9051 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9059 int surfacefirsttriangle;
9060 int surfacenumtriangles;
9061 int surfacefirstvertex;
9062 int surfaceendvertex;
9063 int surfacenumvertices;
9064 int batchnumsurfaces = texturenumsurfaces;
9065 int batchnumvertices;
9066 int batchnumtriangles;
9070 qboolean dynamicvertex;
9073 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9076 q3shaderinfo_deform_t *deform;
9077 const msurface_t *surface, *firstsurface;
9078 r_vertexmesh_t *vertexmesh;
9079 if (!texturenumsurfaces)
9081 // find vertex range of this surface batch
9083 firstsurface = texturesurfacelist[0];
9084 firsttriangle = firstsurface->num_firsttriangle;
9085 batchnumvertices = 0;
9086 batchnumtriangles = 0;
9087 firstvertex = endvertex = firstsurface->num_firstvertex;
9088 for (i = 0;i < texturenumsurfaces;i++)
9090 surface = texturesurfacelist[i];
9091 if (surface != firstsurface + i)
9093 surfacefirstvertex = surface->num_firstvertex;
9094 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
9095 surfacenumvertices = surface->num_vertices;
9096 surfacenumtriangles = surface->num_triangles;
9097 if (firstvertex > surfacefirstvertex)
9098 firstvertex = surfacefirstvertex;
9099 if (endvertex < surfaceendvertex)
9100 endvertex = surfaceendvertex;
9101 batchnumvertices += surfacenumvertices;
9102 batchnumtriangles += surfacenumtriangles;
9105 r_refdef.stats[r_stat_batch_batches]++;
9107 r_refdef.stats[r_stat_batch_withgaps]++;
9108 r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
9109 r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
9110 r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
9112 // we now know the vertex range used, and if there are any gaps in it
9113 rsurface.batchfirstvertex = firstvertex;
9114 rsurface.batchnumvertices = endvertex - firstvertex;
9115 rsurface.batchfirsttriangle = firsttriangle;
9116 rsurface.batchnumtriangles = batchnumtriangles;
9118 // this variable holds flags for which properties have been updated that
9119 // may require regenerating vertexmesh array...
9122 // check if any dynamic vertex processing must occur
9123 dynamicvertex = false;
9125 // a cvar to force the dynamic vertex path to be taken, for debugging
9126 if (r_batch_debugdynamicvertexpath.integer)
9130 r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9131 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9132 r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9133 r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9135 dynamicvertex = true;
9138 // if there is a chance of animated vertex colors, it's a dynamic batch
9139 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9143 r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9144 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9145 r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9146 r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9148 dynamicvertex = true;
9149 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9152 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9154 switch (deform->deform)
9157 case Q3DEFORM_PROJECTIONSHADOW:
9158 case Q3DEFORM_TEXT0:
9159 case Q3DEFORM_TEXT1:
9160 case Q3DEFORM_TEXT2:
9161 case Q3DEFORM_TEXT3:
9162 case Q3DEFORM_TEXT4:
9163 case Q3DEFORM_TEXT5:
9164 case Q3DEFORM_TEXT6:
9165 case Q3DEFORM_TEXT7:
9168 case Q3DEFORM_AUTOSPRITE:
9171 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9172 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9173 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9174 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9176 dynamicvertex = true;
9177 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9178 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9180 case Q3DEFORM_AUTOSPRITE2:
9183 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9184 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9185 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9186 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9188 dynamicvertex = true;
9189 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9190 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9192 case Q3DEFORM_NORMAL:
9195 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9196 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9197 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9198 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9200 dynamicvertex = true;
9201 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9202 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9205 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9206 break; // if wavefunc is a nop, ignore this transform
9209 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9210 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9211 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9212 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9214 dynamicvertex = true;
9215 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9216 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9218 case Q3DEFORM_BULGE:
9221 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9222 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9223 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9224 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9226 dynamicvertex = true;
9227 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9228 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9231 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9232 break; // if wavefunc is a nop, ignore this transform
9235 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9236 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9237 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9238 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9240 dynamicvertex = true;
9241 batchneed |= BATCHNEED_ARRAY_VERTEX;
9242 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9246 switch(rsurface.texture->tcgen.tcgen)
9249 case Q3TCGEN_TEXTURE:
9251 case Q3TCGEN_LIGHTMAP:
9254 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9255 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9256 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9257 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9259 dynamicvertex = true;
9260 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9261 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9263 case Q3TCGEN_VECTOR:
9266 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9267 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9268 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9269 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9271 dynamicvertex = true;
9272 batchneed |= BATCHNEED_ARRAY_VERTEX;
9273 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9275 case Q3TCGEN_ENVIRONMENT:
9278 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9279 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9280 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9281 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9283 dynamicvertex = true;
9284 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9285 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9288 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9292 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9293 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9294 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9295 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9297 dynamicvertex = true;
9298 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9299 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9302 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9306 r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9307 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9308 r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9309 r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9311 dynamicvertex = true;
9312 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9315 // when the model data has no vertex buffer (dynamic mesh), we need to
9317 if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9318 batchneed |= BATCHNEED_NOGAPS;
9320 // the caller can specify BATCHNEED_NOGAPS to force a batch with
9321 // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9322 // we ensure this by treating the vertex batch as dynamic...
9323 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9327 r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9328 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9329 r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9330 r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9332 dynamicvertex = true;
9337 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9338 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
9339 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
9340 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
9341 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9342 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9343 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9344 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL) batchneed |= BATCHNEED_ARRAY_SKELETAL;
9347 // if needsupdate, we have to do a dynamic vertex batch for sure
9348 if (needsupdate & batchneed)
9352 r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9353 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9354 r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9355 r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9357 dynamicvertex = true;
9360 // see if we need to build vertexmesh from arrays
9361 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9365 r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9366 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9367 r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9368 r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9370 dynamicvertex = true;
9373 // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9374 if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9375 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9377 rsurface.batchvertex3f = rsurface.modelvertex3f;
9378 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9379 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9380 rsurface.batchsvector3f = rsurface.modelsvector3f;
9381 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9382 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9383 rsurface.batchtvector3f = rsurface.modeltvector3f;
9384 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9385 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9386 rsurface.batchnormal3f = rsurface.modelnormal3f;
9387 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9388 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9389 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9390 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
9391 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
9392 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9393 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
9394 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
9395 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9396 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9397 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9398 rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9399 rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9400 rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9401 rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9402 rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9403 rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9404 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9405 rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9406 rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9407 rsurface.batchelement3i = rsurface.modelelement3i;
9408 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9409 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9410 rsurface.batchelement3s = rsurface.modelelement3s;
9411 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9412 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9413 rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9414 rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9415 rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9416 rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9417 rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9419 // if any dynamic vertex processing has to occur in software, we copy the
9420 // entire surface list together before processing to rebase the vertices
9421 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9423 // if any gaps exist and we do not have a static vertex buffer, we have to
9424 // copy the surface list together to avoid wasting upload bandwidth on the
9425 // vertices in the gaps.
9427 // if gaps exist and we have a static vertex buffer, we can choose whether
9428 // to combine the index buffer ranges into one dynamic index buffer or
9429 // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9431 // in many cases the batch is reduced to one draw call.
9433 rsurface.batchmultidraw = false;
9434 rsurface.batchmultidrawnumsurfaces = 0;
9435 rsurface.batchmultidrawsurfacelist = NULL;
9439 // static vertex data, just set pointers...
9440 rsurface.batchgeneratedvertex = false;
9441 // if there are gaps, we want to build a combined index buffer,
9442 // otherwise use the original static buffer with an appropriate offset
9445 r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9446 r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9447 r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9448 r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9449 if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9451 rsurface.batchmultidraw = true;
9452 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9453 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9456 // build a new triangle elements array for this batch
9457 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9458 rsurface.batchfirsttriangle = 0;
9460 for (i = 0;i < texturenumsurfaces;i++)
9462 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9463 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9464 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9465 numtriangles += surfacenumtriangles;
9467 rsurface.batchelement3i_indexbuffer = NULL;
9468 rsurface.batchelement3i_bufferoffset = 0;
9469 rsurface.batchelement3s = NULL;
9470 rsurface.batchelement3s_indexbuffer = NULL;
9471 rsurface.batchelement3s_bufferoffset = 0;
9472 if (endvertex <= 65536)
9474 // make a 16bit (unsigned short) index array if possible
9475 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9476 for (i = 0;i < numtriangles*3;i++)
9477 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9479 // upload buffer data for the copytriangles batch
9480 if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9482 if (rsurface.batchelement3s)
9483 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9484 else if (rsurface.batchelement3i)
9485 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9490 r_refdef.stats[r_stat_batch_fast_batches] += 1;
9491 r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9492 r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9493 r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9498 // something needs software processing, do it for real...
9499 // we only directly handle separate array data in this case and then
9500 // generate interleaved data if needed...
9501 rsurface.batchgeneratedvertex = true;
9502 r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9503 r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9504 r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9505 r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9507 // now copy the vertex data into a combined array and make an index array
9508 // (this is what Quake3 does all the time)
9509 // we also apply any skeletal animation here that would have been done in
9510 // the vertex shader, because most of the dynamic vertex animation cases
9511 // need actual vertex positions and normals
9512 //if (dynamicvertex)
9514 rsurface.batchvertexmesh = NULL;
9515 rsurface.batchvertexmesh_vertexbuffer = NULL;
9516 rsurface.batchvertexmesh_bufferoffset = 0;
9517 rsurface.batchvertex3f = NULL;
9518 rsurface.batchvertex3f_vertexbuffer = NULL;
9519 rsurface.batchvertex3f_bufferoffset = 0;
9520 rsurface.batchsvector3f = NULL;
9521 rsurface.batchsvector3f_vertexbuffer = NULL;
9522 rsurface.batchsvector3f_bufferoffset = 0;
9523 rsurface.batchtvector3f = NULL;
9524 rsurface.batchtvector3f_vertexbuffer = NULL;
9525 rsurface.batchtvector3f_bufferoffset = 0;
9526 rsurface.batchnormal3f = NULL;
9527 rsurface.batchnormal3f_vertexbuffer = NULL;
9528 rsurface.batchnormal3f_bufferoffset = 0;
9529 rsurface.batchlightmapcolor4f = NULL;
9530 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9531 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9532 rsurface.batchtexcoordtexture2f = NULL;
9533 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9534 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9535 rsurface.batchtexcoordlightmap2f = NULL;
9536 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9537 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9538 rsurface.batchskeletalindex4ub = NULL;
9539 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9540 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9541 rsurface.batchskeletalweight4ub = NULL;
9542 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9543 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9544 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9545 rsurface.batchelement3i_indexbuffer = NULL;
9546 rsurface.batchelement3i_bufferoffset = 0;
9547 rsurface.batchelement3s = NULL;
9548 rsurface.batchelement3s_indexbuffer = NULL;
9549 rsurface.batchelement3s_bufferoffset = 0;
9550 rsurface.batchskeletaltransform3x4buffer = NULL;
9551 rsurface.batchskeletaltransform3x4offset = 0;
9552 rsurface.batchskeletaltransform3x4size = 0;
9553 // we'll only be setting up certain arrays as needed
9554 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9555 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9556 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9557 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9558 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9559 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9560 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9562 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9563 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9565 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9566 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9567 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9568 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9569 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9570 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9571 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9573 rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9574 rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9578 for (i = 0;i < texturenumsurfaces;i++)
9580 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9581 surfacenumvertices = texturesurfacelist[i]->num_vertices;
9582 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9583 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9584 // copy only the data requested
9585 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9586 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9587 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9589 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9591 if (rsurface.batchvertex3f)
9592 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9594 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9596 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9598 if (rsurface.modelnormal3f)
9599 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9601 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9603 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9605 if (rsurface.modelsvector3f)
9607 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9608 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9612 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9613 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9616 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9618 if (rsurface.modellightmapcolor4f)
9619 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9621 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9623 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9625 if (rsurface.modeltexcoordtexture2f)
9626 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9628 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9630 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9632 if (rsurface.modeltexcoordlightmap2f)
9633 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9635 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9637 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9639 if (rsurface.modelskeletalindex4ub)
9641 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9642 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9646 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9647 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9648 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9649 for (j = 0;j < surfacenumvertices;j++)
9654 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9655 numvertices += surfacenumvertices;
9656 numtriangles += surfacenumtriangles;
9659 // generate a 16bit index array as well if possible
9660 // (in general, dynamic batches fit)
9661 if (numvertices <= 65536)
9663 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9664 for (i = 0;i < numtriangles*3;i++)
9665 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9668 // since we've copied everything, the batch now starts at 0
9669 rsurface.batchfirstvertex = 0;
9670 rsurface.batchnumvertices = batchnumvertices;
9671 rsurface.batchfirsttriangle = 0;
9672 rsurface.batchnumtriangles = batchnumtriangles;
9675 // apply skeletal animation that would have been done in the vertex shader
9676 if (rsurface.batchskeletaltransform3x4)
9678 const unsigned char *si;
9679 const unsigned char *sw;
9681 const float *b = rsurface.batchskeletaltransform3x4;
9682 float *vp, *vs, *vt, *vn;
9684 float m[3][4], n[3][4];
9685 float tp[3], ts[3], tt[3], tn[3];
9686 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9687 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9688 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9689 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9690 si = rsurface.batchskeletalindex4ub;
9691 sw = rsurface.batchskeletalweight4ub;
9692 vp = rsurface.batchvertex3f;
9693 vs = rsurface.batchsvector3f;
9694 vt = rsurface.batchtvector3f;
9695 vn = rsurface.batchnormal3f;
9696 memset(m[0], 0, sizeof(m));
9697 memset(n[0], 0, sizeof(n));
9698 for (i = 0;i < batchnumvertices;i++)
9700 t[0] = b + si[0]*12;
9703 // common case - only one matrix
9717 else if (sw[2] + sw[3])
9720 t[1] = b + si[1]*12;
9721 t[2] = b + si[2]*12;
9722 t[3] = b + si[3]*12;
9723 w[0] = sw[0] * (1.0f / 255.0f);
9724 w[1] = sw[1] * (1.0f / 255.0f);
9725 w[2] = sw[2] * (1.0f / 255.0f);
9726 w[3] = sw[3] * (1.0f / 255.0f);
9727 // blend the matrices
9728 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9729 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9730 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9731 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9732 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9733 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9734 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9735 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9736 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9737 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9738 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9739 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9744 t[1] = b + si[1]*12;
9745 w[0] = sw[0] * (1.0f / 255.0f);
9746 w[1] = sw[1] * (1.0f / 255.0f);
9747 // blend the matrices
9748 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9749 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9750 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9751 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9752 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9753 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9754 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9755 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9756 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9757 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9758 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9759 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9763 // modify the vertex
9765 vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9766 vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9767 vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9771 // the normal transformation matrix is a set of cross products...
9772 CrossProduct(m[1], m[2], n[0]);
9773 CrossProduct(m[2], m[0], n[1]);
9774 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9776 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9777 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9778 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9779 VectorNormalize(vn);
9784 vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9785 vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9786 vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9787 VectorNormalize(vs);
9790 vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9791 vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9792 vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9793 VectorNormalize(vt);
9798 rsurface.batchskeletaltransform3x4 = NULL;
9799 rsurface.batchskeletalnumtransforms = 0;
9802 // q1bsp surfaces rendered in vertex color mode have to have colors
9803 // calculated based on lightstyles
9804 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9806 // generate color arrays for the surfaces in this list
9811 const unsigned char *lm;
9812 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9813 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9814 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9816 for (i = 0;i < texturenumsurfaces;i++)
9818 surface = texturesurfacelist[i];
9819 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9820 surfacenumvertices = surface->num_vertices;
9821 if (surface->lightmapinfo->samples)
9823 for (j = 0;j < surfacenumvertices;j++)
9825 lm = surface->lightmapinfo->samples + offsets[j];
9826 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9827 VectorScale(lm, scale, c);
9828 if (surface->lightmapinfo->styles[1] != 255)
9830 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9832 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9833 VectorMA(c, scale, lm, c);
9834 if (surface->lightmapinfo->styles[2] != 255)
9837 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9838 VectorMA(c, scale, lm, c);
9839 if (surface->lightmapinfo->styles[3] != 255)
9842 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9843 VectorMA(c, scale, lm, c);
9850 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);
9856 for (j = 0;j < surfacenumvertices;j++)
9858 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9865 // if vertices are deformed (sprite flares and things in maps, possibly
9866 // water waves, bulges and other deformations), modify the copied vertices
9868 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9871 switch (deform->deform)
9874 case Q3DEFORM_PROJECTIONSHADOW:
9875 case Q3DEFORM_TEXT0:
9876 case Q3DEFORM_TEXT1:
9877 case Q3DEFORM_TEXT2:
9878 case Q3DEFORM_TEXT3:
9879 case Q3DEFORM_TEXT4:
9880 case Q3DEFORM_TEXT5:
9881 case Q3DEFORM_TEXT6:
9882 case Q3DEFORM_TEXT7:
9885 case Q3DEFORM_AUTOSPRITE:
9886 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9887 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9888 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9889 VectorNormalize(newforward);
9890 VectorNormalize(newright);
9891 VectorNormalize(newup);
9892 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9893 // rsurface.batchvertex3f_vertexbuffer = NULL;
9894 // rsurface.batchvertex3f_bufferoffset = 0;
9895 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9896 // rsurface.batchsvector3f_vertexbuffer = NULL;
9897 // rsurface.batchsvector3f_bufferoffset = 0;
9898 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9899 // rsurface.batchtvector3f_vertexbuffer = NULL;
9900 // rsurface.batchtvector3f_bufferoffset = 0;
9901 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9902 // rsurface.batchnormal3f_vertexbuffer = NULL;
9903 // rsurface.batchnormal3f_bufferoffset = 0;
9904 // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9905 if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9906 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9907 if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9908 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);
9909 // a single autosprite surface can contain multiple sprites...
9910 for (j = 0;j < batchnumvertices - 3;j += 4)
9912 VectorClear(center);
9913 for (i = 0;i < 4;i++)
9914 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9915 VectorScale(center, 0.25f, center);
9916 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9917 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9918 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9919 for (i = 0;i < 4;i++)
9921 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9922 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9925 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9926 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9927 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);
9929 case Q3DEFORM_AUTOSPRITE2:
9930 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9931 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9932 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9933 VectorNormalize(newforward);
9934 VectorNormalize(newright);
9935 VectorNormalize(newup);
9936 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9937 // rsurface.batchvertex3f_vertexbuffer = NULL;
9938 // rsurface.batchvertex3f_bufferoffset = 0;
9940 const float *v1, *v2;
9950 memset(shortest, 0, sizeof(shortest));
9951 // a single autosprite surface can contain multiple sprites...
9952 for (j = 0;j < batchnumvertices - 3;j += 4)
9954 VectorClear(center);
9955 for (i = 0;i < 4;i++)
9956 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9957 VectorScale(center, 0.25f, center);
9958 // find the two shortest edges, then use them to define the
9959 // axis vectors for rotating around the central axis
9960 for (i = 0;i < 6;i++)
9962 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9963 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9964 l = VectorDistance2(v1, v2);
9965 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9967 l += (1.0f / 1024.0f);
9968 if (shortest[0].length2 > l || i == 0)
9970 shortest[1] = shortest[0];
9971 shortest[0].length2 = l;
9972 shortest[0].v1 = v1;
9973 shortest[0].v2 = v2;
9975 else if (shortest[1].length2 > l || i == 1)
9977 shortest[1].length2 = l;
9978 shortest[1].v1 = v1;
9979 shortest[1].v2 = v2;
9982 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9983 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9984 // this calculates the right vector from the shortest edge
9985 // and the up vector from the edge midpoints
9986 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9987 VectorNormalize(right);
9988 VectorSubtract(end, start, up);
9989 VectorNormalize(up);
9990 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9991 VectorSubtract(rsurface.localvieworigin, center, forward);
9992 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9993 VectorNegate(forward, forward);
9994 VectorReflect(forward, 0, up, forward);
9995 VectorNormalize(forward);
9996 CrossProduct(up, forward, newright);
9997 VectorNormalize(newright);
9998 // rotate the quad around the up axis vector, this is made
9999 // especially easy by the fact we know the quad is flat,
10000 // so we only have to subtract the center position and
10001 // measure distance along the right vector, and then
10002 // multiply that by the newright vector and add back the
10004 // we also need to subtract the old position to undo the
10005 // displacement from the center, which we do with a
10006 // DotProduct, the subtraction/addition of center is also
10007 // optimized into DotProducts here
10008 l = DotProduct(right, center);
10009 for (i = 0;i < 4;i++)
10011 v1 = rsurface.batchvertex3f + 3*(j+i);
10012 f = DotProduct(right, v1) - l;
10013 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
10017 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
10019 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10020 // rsurface.batchnormal3f_vertexbuffer = NULL;
10021 // rsurface.batchnormal3f_bufferoffset = 0;
10022 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10024 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10026 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10027 // rsurface.batchsvector3f_vertexbuffer = NULL;
10028 // rsurface.batchsvector3f_bufferoffset = 0;
10029 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10030 // rsurface.batchtvector3f_vertexbuffer = NULL;
10031 // rsurface.batchtvector3f_bufferoffset = 0;
10032 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);
10035 case Q3DEFORM_NORMAL:
10036 // deform the normals to make reflections wavey
10037 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10038 rsurface.batchnormal3f_vertexbuffer = NULL;
10039 rsurface.batchnormal3f_bufferoffset = 0;
10040 for (j = 0;j < batchnumvertices;j++)
10043 float *normal = rsurface.batchnormal3f + 3*j;
10044 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
10045 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10046 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10047 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10048 VectorNormalize(normal);
10050 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10052 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10053 // rsurface.batchsvector3f_vertexbuffer = NULL;
10054 // rsurface.batchsvector3f_bufferoffset = 0;
10055 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10056 // rsurface.batchtvector3f_vertexbuffer = NULL;
10057 // rsurface.batchtvector3f_bufferoffset = 0;
10058 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);
10061 case Q3DEFORM_WAVE:
10062 // deform vertex array to make wavey water and flags and such
10063 waveparms[0] = deform->waveparms[0];
10064 waveparms[1] = deform->waveparms[1];
10065 waveparms[2] = deform->waveparms[2];
10066 waveparms[3] = deform->waveparms[3];
10067 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
10068 break; // if wavefunc is a nop, don't make a dynamic vertex array
10069 // this is how a divisor of vertex influence on deformation
10070 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10071 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10072 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10073 // rsurface.batchvertex3f_vertexbuffer = NULL;
10074 // rsurface.batchvertex3f_bufferoffset = 0;
10075 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10076 // rsurface.batchnormal3f_vertexbuffer = NULL;
10077 // rsurface.batchnormal3f_bufferoffset = 0;
10078 for (j = 0;j < batchnumvertices;j++)
10080 // if the wavefunc depends on time, evaluate it per-vertex
10083 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
10084 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10086 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10088 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10089 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10090 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10092 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10093 // rsurface.batchsvector3f_vertexbuffer = NULL;
10094 // rsurface.batchsvector3f_bufferoffset = 0;
10095 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10096 // rsurface.batchtvector3f_vertexbuffer = NULL;
10097 // rsurface.batchtvector3f_bufferoffset = 0;
10098 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);
10101 case Q3DEFORM_BULGE:
10102 // deform vertex array to make the surface have moving bulges
10103 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10104 // rsurface.batchvertex3f_vertexbuffer = NULL;
10105 // rsurface.batchvertex3f_bufferoffset = 0;
10106 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10107 // rsurface.batchnormal3f_vertexbuffer = NULL;
10108 // rsurface.batchnormal3f_bufferoffset = 0;
10109 for (j = 0;j < batchnumvertices;j++)
10111 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
10112 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10114 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10115 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10116 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10118 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10119 // rsurface.batchsvector3f_vertexbuffer = NULL;
10120 // rsurface.batchsvector3f_bufferoffset = 0;
10121 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10122 // rsurface.batchtvector3f_vertexbuffer = NULL;
10123 // rsurface.batchtvector3f_bufferoffset = 0;
10124 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);
10127 case Q3DEFORM_MOVE:
10128 // deform vertex array
10129 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10130 break; // if wavefunc is a nop, don't make a dynamic vertex array
10131 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10132 VectorScale(deform->parms, scale, waveparms);
10133 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10134 // rsurface.batchvertex3f_vertexbuffer = NULL;
10135 // rsurface.batchvertex3f_bufferoffset = 0;
10136 for (j = 0;j < batchnumvertices;j++)
10137 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10142 if (rsurface.batchtexcoordtexture2f)
10144 // generate texcoords based on the chosen texcoord source
10145 switch(rsurface.texture->tcgen.tcgen)
10148 case Q3TCGEN_TEXTURE:
10150 case Q3TCGEN_LIGHTMAP:
10151 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10152 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10153 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10154 if (rsurface.batchtexcoordlightmap2f)
10155 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
10157 case Q3TCGEN_VECTOR:
10158 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10159 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10160 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10161 for (j = 0;j < batchnumvertices;j++)
10163 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
10164 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
10167 case Q3TCGEN_ENVIRONMENT:
10168 // make environment reflections using a spheremap
10169 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10170 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10171 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10172 for (j = 0;j < batchnumvertices;j++)
10174 // identical to Q3A's method, but executed in worldspace so
10175 // carried models can be shiny too
10177 float viewer[3], d, reflected[3], worldreflected[3];
10179 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10180 // VectorNormalize(viewer);
10182 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10184 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10185 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10186 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10187 // note: this is proportinal to viewer, so we can normalize later
10189 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10190 VectorNormalize(worldreflected);
10192 // note: this sphere map only uses world x and z!
10193 // so positive and negative y will LOOK THE SAME.
10194 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10195 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10199 // the only tcmod that needs software vertex processing is turbulent, so
10200 // check for it here and apply the changes if needed
10201 // and we only support that as the first one
10202 // (handling a mixture of turbulent and other tcmods would be problematic
10203 // without punting it entirely to a software path)
10204 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10206 amplitude = rsurface.texture->tcmods[0].parms[1];
10207 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
10208 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10209 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10210 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10211 for (j = 0;j < batchnumvertices;j++)
10213 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);
10214 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10219 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10221 // convert the modified arrays to vertex structs
10222 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10223 // rsurface.batchvertexmesh_vertexbuffer = NULL;
10224 // rsurface.batchvertexmesh_bufferoffset = 0;
10225 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10226 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10227 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10228 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10229 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10230 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10231 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10233 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10235 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10236 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10239 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10240 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10241 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10242 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10243 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10244 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10245 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10246 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10247 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10248 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10250 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10252 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10253 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10258 // upload buffer data for the dynamic batch
10259 if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10261 if (rsurface.batchvertexmesh)
10262 rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10265 if (rsurface.batchvertex3f)
10266 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10267 if (rsurface.batchsvector3f)
10268 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10269 if (rsurface.batchtvector3f)
10270 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10271 if (rsurface.batchnormal3f)
10272 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10273 if (rsurface.batchlightmapcolor4f)
10274 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10275 if (rsurface.batchtexcoordtexture2f)
10276 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10277 if (rsurface.batchtexcoordlightmap2f)
10278 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10279 if (rsurface.batchskeletalindex4ub)
10280 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10281 if (rsurface.batchskeletalweight4ub)
10282 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10284 if (rsurface.batchelement3s)
10285 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10286 else if (rsurface.batchelement3i)
10287 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10291 void RSurf_DrawBatch(void)
10293 // sometimes a zero triangle surface (usually a degenerate patch) makes it
10294 // through the pipeline, killing it earlier in the pipeline would have
10295 // per-surface overhead rather than per-batch overhead, so it's best to
10296 // reject it here, before it hits glDraw.
10297 if (rsurface.batchnumtriangles == 0)
10300 // batch debugging code
10301 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10307 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10308 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10311 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10313 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10315 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10316 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);
10323 if (rsurface.batchmultidraw)
10325 // issue multiple draws rather than copying index data
10326 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10327 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10328 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10329 for (i = 0;i < numsurfaces;)
10331 // combine consecutive surfaces as one draw
10332 for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10333 if (surfacelist[j] != surfacelist[k] + 1)
10335 firstvertex = surfacelist[i]->num_firstvertex;
10336 endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10337 firsttriangle = surfacelist[i]->num_firsttriangle;
10338 endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10339 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);
10345 // there is only one consecutive run of index data (may have been combined)
10346 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);
10350 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10352 // pick the closest matching water plane
10353 int planeindex, vertexindex, bestplaneindex = -1;
10357 r_waterstate_waterplane_t *p;
10358 qboolean prepared = false;
10360 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10362 if(p->camera_entity != rsurface.texture->camera_entity)
10367 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10369 if(rsurface.batchnumvertices == 0)
10372 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10374 Matrix4x4_Transform(&rsurface.matrix, v, vert);
10375 d += fabs(PlaneDiff(vert, &p->plane));
10377 if (bestd > d || bestplaneindex < 0)
10380 bestplaneindex = planeindex;
10383 return bestplaneindex;
10384 // NOTE: this MAY return a totally unrelated water plane; we can ignore
10385 // this situation though, as it might be better to render single larger
10386 // batches with useless stuff (backface culled for example) than to
10387 // render multiple smaller batches
10390 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10393 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10394 rsurface.passcolor4f_vertexbuffer = 0;
10395 rsurface.passcolor4f_bufferoffset = 0;
10396 for (i = 0;i < rsurface.batchnumvertices;i++)
10397 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10400 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10407 if (rsurface.passcolor4f)
10409 // generate color arrays
10410 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10411 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10412 rsurface.passcolor4f_vertexbuffer = 0;
10413 rsurface.passcolor4f_bufferoffset = 0;
10414 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)
10416 f = RSurf_FogVertex(v);
10425 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10426 rsurface.passcolor4f_vertexbuffer = 0;
10427 rsurface.passcolor4f_bufferoffset = 0;
10428 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10430 f = RSurf_FogVertex(v);
10439 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10446 if (!rsurface.passcolor4f)
10448 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10449 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10450 rsurface.passcolor4f_vertexbuffer = 0;
10451 rsurface.passcolor4f_bufferoffset = 0;
10452 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)
10454 f = RSurf_FogVertex(v);
10455 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10456 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10457 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10462 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10467 if (!rsurface.passcolor4f)
10469 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10470 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10471 rsurface.passcolor4f_vertexbuffer = 0;
10472 rsurface.passcolor4f_bufferoffset = 0;
10473 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10482 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10487 if (!rsurface.passcolor4f)
10489 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10490 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10491 rsurface.passcolor4f_vertexbuffer = 0;
10492 rsurface.passcolor4f_bufferoffset = 0;
10493 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10495 c2[0] = c[0] + r_refdef.scene.ambient;
10496 c2[1] = c[1] + r_refdef.scene.ambient;
10497 c2[2] = c[2] + r_refdef.scene.ambient;
10502 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10505 rsurface.passcolor4f = NULL;
10506 rsurface.passcolor4f_vertexbuffer = 0;
10507 rsurface.passcolor4f_bufferoffset = 0;
10508 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10509 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10510 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10511 GL_Color(r, g, b, a);
10512 R_Mesh_TexBind(0, rsurface.lightmaptexture);
10513 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10514 R_Mesh_TexMatrix(0, NULL);
10518 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10520 // TODO: optimize applyfog && applycolor case
10521 // just apply fog if necessary, and tint the fog color array if necessary
10522 rsurface.passcolor4f = NULL;
10523 rsurface.passcolor4f_vertexbuffer = 0;
10524 rsurface.passcolor4f_bufferoffset = 0;
10525 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10526 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10527 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10528 GL_Color(r, g, b, a);
10532 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10535 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10536 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10537 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10538 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10539 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10540 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10541 GL_Color(r, g, b, a);
10545 static void RSurf_DrawBatch_GL11_ClampColor(void)
10550 if (!rsurface.passcolor4f)
10552 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10554 c2[0] = bound(0.0f, c1[0], 1.0f);
10555 c2[1] = bound(0.0f, c1[1], 1.0f);
10556 c2[2] = bound(0.0f, c1[2], 1.0f);
10557 c2[3] = bound(0.0f, c1[3], 1.0f);
10561 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10571 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10572 rsurface.passcolor4f_vertexbuffer = 0;
10573 rsurface.passcolor4f_bufferoffset = 0;
10574 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)
10576 f = -DotProduct(r_refdef.view.forward, n);
10578 f = f * 0.85 + 0.15; // work around so stuff won't get black
10579 f *= r_refdef.lightmapintensity;
10580 Vector4Set(c, f, f, f, 1);
10584 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10586 RSurf_DrawBatch_GL11_ApplyFakeLight();
10587 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10588 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10589 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10590 GL_Color(r, g, b, a);
10594 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10602 vec3_t ambientcolor;
10603 vec3_t diffusecolor;
10607 VectorCopy(rsurface.modellight_lightdir, lightdir);
10608 f = 0.5f * r_refdef.lightmapintensity;
10609 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10610 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10611 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10612 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10613 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10614 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10616 if (VectorLength2(diffusecolor) > 0)
10618 // q3-style directional shading
10619 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10620 rsurface.passcolor4f_vertexbuffer = 0;
10621 rsurface.passcolor4f_bufferoffset = 0;
10622 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)
10624 if ((f = DotProduct(n, lightdir)) > 0)
10625 VectorMA(ambientcolor, f, diffusecolor, c);
10627 VectorCopy(ambientcolor, c);
10634 *applycolor = false;
10638 *r = ambientcolor[0];
10639 *g = ambientcolor[1];
10640 *b = ambientcolor[2];
10641 rsurface.passcolor4f = NULL;
10642 rsurface.passcolor4f_vertexbuffer = 0;
10643 rsurface.passcolor4f_bufferoffset = 0;
10647 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10649 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10650 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10651 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10652 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10653 GL_Color(r, g, b, a);
10657 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10665 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10666 rsurface.passcolor4f_vertexbuffer = 0;
10667 rsurface.passcolor4f_bufferoffset = 0;
10669 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10671 f = 1 - RSurf_FogVertex(v);
10679 void RSurf_SetupDepthAndCulling(void)
10681 // submodels are biased to avoid z-fighting with world surfaces that they
10682 // may be exactly overlapping (avoids z-fighting artifacts on certain
10683 // doors and things in Quake maps)
10684 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10685 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10686 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10687 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10690 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10692 // transparent sky would be ridiculous
10693 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10695 R_SetupShader_Generic_NoTexture(false, false);
10696 skyrenderlater = true;
10697 RSurf_SetupDepthAndCulling();
10698 GL_DepthMask(true);
10699 // LordHavoc: HalfLife maps have freaky skypolys so don't use
10700 // skymasking on them, and Quake3 never did sky masking (unlike
10701 // software Quake and software Quake2), so disable the sky masking
10702 // in Quake3 maps as it causes problems with q3map2 sky tricks,
10703 // and skymasking also looks very bad when noclipping outside the
10704 // level, so don't use it then either.
10705 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.skymasking && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10707 R_Mesh_ResetTextureState();
10708 if (skyrendermasked)
10710 R_SetupShader_DepthOrShadow(false, false, false);
10711 // depth-only (masking)
10712 GL_ColorMask(0,0,0,0);
10713 // just to make sure that braindead drivers don't draw
10714 // anything despite that colormask...
10715 GL_BlendFunc(GL_ZERO, GL_ONE);
10716 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10717 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10721 R_SetupShader_Generic_NoTexture(false, false);
10723 GL_BlendFunc(GL_ONE, GL_ZERO);
10724 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10725 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10726 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10729 if (skyrendermasked)
10730 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10732 R_Mesh_ResetTextureState();
10733 GL_Color(1, 1, 1, 1);
10736 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10737 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10738 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10740 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10744 // render screenspace normalmap to texture
10745 GL_DepthMask(true);
10746 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10751 // bind lightmap texture
10753 // water/refraction/reflection/camera surfaces have to be handled specially
10754 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10756 int start, end, startplaneindex;
10757 for (start = 0;start < texturenumsurfaces;start = end)
10759 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10760 if(startplaneindex < 0)
10762 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10763 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10767 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10769 // now that we have a batch using the same planeindex, render it
10770 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10772 // render water or distortion background
10773 GL_DepthMask(true);
10774 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);
10776 // blend surface on top
10777 GL_DepthMask(false);
10778 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10781 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10783 // render surface with reflection texture as input
10784 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10785 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);
10792 // render surface batch normally
10793 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10794 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);
10798 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10800 // OpenGL 1.3 path - anything not completely ancient
10801 qboolean applycolor;
10804 const texturelayer_t *layer;
10805 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);
10806 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10808 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10811 int layertexrgbscale;
10812 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10814 if (layerindex == 0)
10815 GL_AlphaTest(true);
10818 GL_AlphaTest(false);
10819 GL_DepthFunc(GL_EQUAL);
10822 GL_DepthMask(layer->depthmask && writedepth);
10823 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10824 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10826 layertexrgbscale = 4;
10827 VectorScale(layer->color, 0.25f, layercolor);
10829 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10831 layertexrgbscale = 2;
10832 VectorScale(layer->color, 0.5f, layercolor);
10836 layertexrgbscale = 1;
10837 VectorScale(layer->color, 1.0f, layercolor);
10839 layercolor[3] = layer->color[3];
10840 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10841 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10842 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10843 switch (layer->type)
10845 case TEXTURELAYERTYPE_LITTEXTURE:
10846 // single-pass lightmapped texture with 2x rgbscale
10847 R_Mesh_TexBind(0, r_texture_white);
10848 R_Mesh_TexMatrix(0, NULL);
10849 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10850 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10851 R_Mesh_TexBind(1, layer->texture);
10852 R_Mesh_TexMatrix(1, &layer->texmatrix);
10853 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10854 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10855 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10856 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10857 else if (FAKELIGHT_ENABLED)
10858 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10859 else if (rsurface.uselightmaptexture)
10860 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10862 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10864 case TEXTURELAYERTYPE_TEXTURE:
10865 // singletexture unlit texture with transparency support
10866 R_Mesh_TexBind(0, layer->texture);
10867 R_Mesh_TexMatrix(0, &layer->texmatrix);
10868 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10869 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10870 R_Mesh_TexBind(1, 0);
10871 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10872 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10874 case TEXTURELAYERTYPE_FOG:
10875 // singletexture fogging
10876 if (layer->texture)
10878 R_Mesh_TexBind(0, layer->texture);
10879 R_Mesh_TexMatrix(0, &layer->texmatrix);
10880 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10881 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10885 R_Mesh_TexBind(0, 0);
10886 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10888 R_Mesh_TexBind(1, 0);
10889 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10890 // generate a color array for the fog pass
10891 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10892 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10896 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10899 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10901 GL_DepthFunc(GL_LEQUAL);
10902 GL_AlphaTest(false);
10906 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10908 // OpenGL 1.1 - crusty old voodoo path
10911 const texturelayer_t *layer;
10912 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);
10913 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10915 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10917 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10919 if (layerindex == 0)
10920 GL_AlphaTest(true);
10923 GL_AlphaTest(false);
10924 GL_DepthFunc(GL_EQUAL);
10927 GL_DepthMask(layer->depthmask && writedepth);
10928 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10929 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10930 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10931 switch (layer->type)
10933 case TEXTURELAYERTYPE_LITTEXTURE:
10934 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10936 // two-pass lit texture with 2x rgbscale
10937 // first the lightmap pass
10938 R_Mesh_TexBind(0, r_texture_white);
10939 R_Mesh_TexMatrix(0, NULL);
10940 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10941 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10942 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10943 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10944 else if (FAKELIGHT_ENABLED)
10945 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10946 else if (rsurface.uselightmaptexture)
10947 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10949 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10950 // then apply the texture to it
10951 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10952 R_Mesh_TexBind(0, layer->texture);
10953 R_Mesh_TexMatrix(0, &layer->texmatrix);
10954 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10955 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10956 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);
10960 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10961 R_Mesh_TexBind(0, layer->texture);
10962 R_Mesh_TexMatrix(0, &layer->texmatrix);
10963 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10964 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10965 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10966 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);
10967 else if (FAKELIGHT_ENABLED)
10968 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);
10970 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);
10973 case TEXTURELAYERTYPE_TEXTURE:
10974 // singletexture unlit texture with transparency support
10975 R_Mesh_TexBind(0, layer->texture);
10976 R_Mesh_TexMatrix(0, &layer->texmatrix);
10977 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10978 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10979 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);
10981 case TEXTURELAYERTYPE_FOG:
10982 // singletexture fogging
10983 if (layer->texture)
10985 R_Mesh_TexBind(0, layer->texture);
10986 R_Mesh_TexMatrix(0, &layer->texmatrix);
10987 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10988 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10992 R_Mesh_TexBind(0, 0);
10993 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10995 // generate a color array for the fog pass
10996 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10997 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
11001 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11004 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11006 GL_DepthFunc(GL_LEQUAL);
11007 GL_AlphaTest(false);
11011 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11015 r_vertexgeneric_t *batchvertex;
11018 // R_Mesh_ResetTextureState();
11019 R_SetupShader_Generic_NoTexture(false, false);
11021 if(rsurface.texture && rsurface.texture->currentskinframe)
11023 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
11024 c[3] *= rsurface.texture->currentalpha;
11034 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
11036 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
11037 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
11038 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
11041 // brighten it up (as texture value 127 means "unlit")
11042 c[0] *= 2 * r_refdef.view.colorscale;
11043 c[1] *= 2 * r_refdef.view.colorscale;
11044 c[2] *= 2 * r_refdef.view.colorscale;
11046 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11047 c[3] *= r_wateralpha.value;
11049 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11051 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11052 GL_DepthMask(false);
11054 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11056 GL_BlendFunc(GL_ONE, GL_ONE);
11057 GL_DepthMask(false);
11059 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11061 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11062 GL_DepthMask(false);
11064 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11066 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11067 GL_DepthMask(false);
11071 GL_BlendFunc(GL_ONE, GL_ZERO);
11072 GL_DepthMask(writedepth);
11075 if (r_showsurfaces.integer == 3)
11077 rsurface.passcolor4f = NULL;
11079 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11081 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11083 rsurface.passcolor4f = NULL;
11084 rsurface.passcolor4f_vertexbuffer = 0;
11085 rsurface.passcolor4f_bufferoffset = 0;
11087 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11089 qboolean applycolor = true;
11092 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11094 r_refdef.lightmapintensity = 1;
11095 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
11096 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11098 else if (FAKELIGHT_ENABLED)
11100 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11102 r_refdef.lightmapintensity = r_fakelight_intensity.value;
11103 RSurf_DrawBatch_GL11_ApplyFakeLight();
11104 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11108 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11110 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11111 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11112 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11115 if(!rsurface.passcolor4f)
11116 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11118 RSurf_DrawBatch_GL11_ApplyAmbient();
11119 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11120 if(r_refdef.fogenabled)
11121 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11122 RSurf_DrawBatch_GL11_ClampColor();
11124 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11125 R_SetupShader_Generic_NoTexture(false, false);
11128 else if (!r_refdef.view.showdebug)
11130 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11131 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11132 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11134 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11135 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11137 R_Mesh_PrepareVertices_Generic_Unlock();
11140 else if (r_showsurfaces.integer == 4)
11142 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11143 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11144 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11146 unsigned char d = (vi << 3) * (1.0f / 256.0f);
11147 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11148 Vector4Set(batchvertex[vi].color4f, d, d, d, 1);
11150 R_Mesh_PrepareVertices_Generic_Unlock();
11153 else if (r_showsurfaces.integer == 2)
11156 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11157 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11158 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11160 unsigned char d = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11161 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11162 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11163 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11164 Vector4Set(batchvertex[j*3+0].color4f, d, d, d, 1);
11165 Vector4Set(batchvertex[j*3+1].color4f, d, d, d, 1);
11166 Vector4Set(batchvertex[j*3+2].color4f, d, d, d, 1);
11168 R_Mesh_PrepareVertices_Generic_Unlock();
11169 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11173 int texturesurfaceindex;
11175 const msurface_t *surface;
11176 float surfacecolor4f[4];
11177 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11178 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11180 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11182 surface = texturesurfacelist[texturesurfaceindex];
11183 k = (int)(((size_t)surface) / sizeof(msurface_t));
11184 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11185 for (j = 0;j < surface->num_vertices;j++)
11187 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11188 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11192 R_Mesh_PrepareVertices_Generic_Unlock();
11197 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11200 RSurf_SetupDepthAndCulling();
11201 if (r_showsurfaces.integer)
11203 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11206 switch (vid.renderpath)
11208 case RENDERPATH_GL20:
11209 case RENDERPATH_D3D9:
11210 case RENDERPATH_D3D10:
11211 case RENDERPATH_D3D11:
11212 case RENDERPATH_SOFT:
11213 case RENDERPATH_GLES2:
11214 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11216 case RENDERPATH_GL13:
11217 case RENDERPATH_GLES1:
11218 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11220 case RENDERPATH_GL11:
11221 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11227 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11230 RSurf_SetupDepthAndCulling();
11231 if (r_showsurfaces.integer)
11233 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11236 switch (vid.renderpath)
11238 case RENDERPATH_GL20:
11239 case RENDERPATH_D3D9:
11240 case RENDERPATH_D3D10:
11241 case RENDERPATH_D3D11:
11242 case RENDERPATH_SOFT:
11243 case RENDERPATH_GLES2:
11244 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11246 case RENDERPATH_GL13:
11247 case RENDERPATH_GLES1:
11248 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11250 case RENDERPATH_GL11:
11251 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11257 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11260 int texturenumsurfaces, endsurface;
11261 texture_t *texture;
11262 const msurface_t *surface;
11263 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11265 // if the model is static it doesn't matter what value we give for
11266 // wantnormals and wanttangents, so this logic uses only rules applicable
11267 // to a model, knowing that they are meaningless otherwise
11268 if (ent == r_refdef.scene.worldentity)
11269 RSurf_ActiveWorldEntity();
11270 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11271 RSurf_ActiveModelEntity(ent, false, false, false);
11274 switch (vid.renderpath)
11276 case RENDERPATH_GL20:
11277 case RENDERPATH_D3D9:
11278 case RENDERPATH_D3D10:
11279 case RENDERPATH_D3D11:
11280 case RENDERPATH_SOFT:
11281 case RENDERPATH_GLES2:
11282 RSurf_ActiveModelEntity(ent, true, true, false);
11284 case RENDERPATH_GL11:
11285 case RENDERPATH_GL13:
11286 case RENDERPATH_GLES1:
11287 RSurf_ActiveModelEntity(ent, true, false, false);
11292 if (r_transparentdepthmasking.integer)
11294 qboolean setup = false;
11295 for (i = 0;i < numsurfaces;i = j)
11298 surface = rsurface.modelsurfaces + surfacelist[i];
11299 texture = surface->texture;
11300 rsurface.texture = R_GetCurrentTexture(texture);
11301 rsurface.lightmaptexture = NULL;
11302 rsurface.deluxemaptexture = NULL;
11303 rsurface.uselightmaptexture = false;
11304 // scan ahead until we find a different texture
11305 endsurface = min(i + 1024, numsurfaces);
11306 texturenumsurfaces = 0;
11307 texturesurfacelist[texturenumsurfaces++] = surface;
11308 for (;j < endsurface;j++)
11310 surface = rsurface.modelsurfaces + surfacelist[j];
11311 if (texture != surface->texture)
11313 texturesurfacelist[texturenumsurfaces++] = surface;
11315 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11317 // render the range of surfaces as depth
11321 GL_ColorMask(0,0,0,0);
11323 GL_DepthTest(true);
11324 GL_BlendFunc(GL_ONE, GL_ZERO);
11325 GL_DepthMask(true);
11326 // R_Mesh_ResetTextureState();
11328 RSurf_SetupDepthAndCulling();
11329 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11330 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11331 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11335 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11338 for (i = 0;i < numsurfaces;i = j)
11341 surface = rsurface.modelsurfaces + surfacelist[i];
11342 texture = surface->texture;
11343 rsurface.texture = R_GetCurrentTexture(texture);
11344 // scan ahead until we find a different texture
11345 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11346 texturenumsurfaces = 0;
11347 texturesurfacelist[texturenumsurfaces++] = surface;
11348 if(FAKELIGHT_ENABLED)
11350 rsurface.lightmaptexture = NULL;
11351 rsurface.deluxemaptexture = NULL;
11352 rsurface.uselightmaptexture = false;
11353 for (;j < endsurface;j++)
11355 surface = rsurface.modelsurfaces + surfacelist[j];
11356 if (texture != surface->texture)
11358 texturesurfacelist[texturenumsurfaces++] = surface;
11363 rsurface.lightmaptexture = surface->lightmaptexture;
11364 rsurface.deluxemaptexture = surface->deluxemaptexture;
11365 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11366 for (;j < endsurface;j++)
11368 surface = rsurface.modelsurfaces + surfacelist[j];
11369 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11371 texturesurfacelist[texturenumsurfaces++] = surface;
11374 // render the range of surfaces
11375 if (ent == r_refdef.scene.worldentity)
11376 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11378 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11380 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11383 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11385 // transparent surfaces get pushed off into the transparent queue
11386 int surfacelistindex;
11387 const msurface_t *surface;
11388 vec3_t tempcenter, center;
11389 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11391 surface = texturesurfacelist[surfacelistindex];
11392 if (r_transparent_sortsurfacesbynearest.integer)
11394 tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11395 tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11396 tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11400 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11401 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11402 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11404 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11405 if (rsurface.entity->transparent_offset) // transparent offset
11407 center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11408 center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11409 center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11411 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);
11415 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11417 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11419 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11421 RSurf_SetupDepthAndCulling();
11422 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11423 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11424 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11428 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11432 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11435 if (!rsurface.texture->currentnumlayers)
11437 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11438 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11440 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11442 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11443 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11444 else if (!rsurface.texture->currentnumlayers)
11446 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11448 // in the deferred case, transparent surfaces were queued during prepass
11449 if (!r_shadow_usingdeferredprepass)
11450 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11454 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11455 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11460 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11463 texture_t *texture;
11464 R_FrameData_SetMark();
11465 // break the surface list down into batches by texture and use of lightmapping
11466 for (i = 0;i < numsurfaces;i = j)
11469 // texture is the base texture pointer, rsurface.texture is the
11470 // current frame/skin the texture is directing us to use (for example
11471 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11472 // use skin 1 instead)
11473 texture = surfacelist[i]->texture;
11474 rsurface.texture = R_GetCurrentTexture(texture);
11475 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11477 // if this texture is not the kind we want, skip ahead to the next one
11478 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11482 if(FAKELIGHT_ENABLED || depthonly || prepass)
11484 rsurface.lightmaptexture = NULL;
11485 rsurface.deluxemaptexture = NULL;
11486 rsurface.uselightmaptexture = false;
11487 // simply scan ahead until we find a different texture or lightmap state
11488 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11493 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11494 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11495 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11496 // simply scan ahead until we find a different texture or lightmap state
11497 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11500 // render the range of surfaces
11501 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11503 R_FrameData_ReturnToMark();
11506 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11510 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11513 if (!rsurface.texture->currentnumlayers)
11515 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11516 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11518 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11520 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11521 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11522 else if (!rsurface.texture->currentnumlayers)
11524 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11526 // in the deferred case, transparent surfaces were queued during prepass
11527 if (!r_shadow_usingdeferredprepass)
11528 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11532 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11533 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11538 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11541 texture_t *texture;
11542 R_FrameData_SetMark();
11543 // break the surface list down into batches by texture and use of lightmapping
11544 for (i = 0;i < numsurfaces;i = j)
11547 // texture is the base texture pointer, rsurface.texture is the
11548 // current frame/skin the texture is directing us to use (for example
11549 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11550 // use skin 1 instead)
11551 texture = surfacelist[i]->texture;
11552 rsurface.texture = R_GetCurrentTexture(texture);
11553 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11555 // if this texture is not the kind we want, skip ahead to the next one
11556 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11560 if(FAKELIGHT_ENABLED || depthonly || prepass)
11562 rsurface.lightmaptexture = NULL;
11563 rsurface.deluxemaptexture = NULL;
11564 rsurface.uselightmaptexture = false;
11565 // simply scan ahead until we find a different texture or lightmap state
11566 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11571 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11572 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11573 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11574 // simply scan ahead until we find a different texture or lightmap state
11575 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11578 // render the range of surfaces
11579 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11581 R_FrameData_ReturnToMark();
11584 float locboxvertex3f[6*4*3] =
11586 1,0,1, 1,0,0, 1,1,0, 1,1,1,
11587 0,1,1, 0,1,0, 0,0,0, 0,0,1,
11588 1,1,1, 1,1,0, 0,1,0, 0,1,1,
11589 0,0,1, 0,0,0, 1,0,0, 1,0,1,
11590 0,0,1, 1,0,1, 1,1,1, 0,1,1,
11591 1,0,0, 0,0,0, 0,1,0, 1,1,0
11594 unsigned short locboxelements[6*2*3] =
11599 12,13,14, 12,14,15,
11600 16,17,18, 16,18,19,
11604 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11607 cl_locnode_t *loc = (cl_locnode_t *)ent;
11609 float vertex3f[6*4*3];
11611 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11612 GL_DepthMask(false);
11613 GL_DepthRange(0, 1);
11614 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11615 GL_DepthTest(true);
11616 GL_CullFace(GL_NONE);
11617 R_EntityMatrix(&identitymatrix);
11619 // R_Mesh_ResetTextureState();
11621 i = surfacelist[0];
11622 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11623 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11624 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11625 surfacelist[0] < 0 ? 0.5f : 0.125f);
11627 if (VectorCompare(loc->mins, loc->maxs))
11629 VectorSet(size, 2, 2, 2);
11630 VectorMA(loc->mins, -0.5f, size, mins);
11634 VectorCopy(loc->mins, mins);
11635 VectorSubtract(loc->maxs, loc->mins, size);
11638 for (i = 0;i < 6*4*3;)
11639 for (j = 0;j < 3;j++, i++)
11640 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11642 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11643 R_SetupShader_Generic_NoTexture(false, false);
11644 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11647 void R_DrawLocs(void)
11650 cl_locnode_t *loc, *nearestloc;
11652 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11653 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11655 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11656 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11660 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11662 if (decalsystem->decals)
11663 Mem_Free(decalsystem->decals);
11664 memset(decalsystem, 0, sizeof(*decalsystem));
11667 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)
11670 tridecal_t *decals;
11673 // expand or initialize the system
11674 if (decalsystem->maxdecals <= decalsystem->numdecals)
11676 decalsystem_t old = *decalsystem;
11677 qboolean useshortelements;
11678 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11679 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11680 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)));
11681 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11682 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11683 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11684 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11685 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11686 if (decalsystem->numdecals)
11687 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11689 Mem_Free(old.decals);
11690 for (i = 0;i < decalsystem->maxdecals*3;i++)
11691 decalsystem->element3i[i] = i;
11692 if (useshortelements)
11693 for (i = 0;i < decalsystem->maxdecals*3;i++)
11694 decalsystem->element3s[i] = i;
11697 // grab a decal and search for another free slot for the next one
11698 decals = decalsystem->decals;
11699 decal = decalsystem->decals + (i = decalsystem->freedecal++);
11700 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11702 decalsystem->freedecal = i;
11703 if (decalsystem->numdecals <= i)
11704 decalsystem->numdecals = i + 1;
11706 // initialize the decal
11708 decal->triangleindex = triangleindex;
11709 decal->surfaceindex = surfaceindex;
11710 decal->decalsequence = decalsequence;
11711 decal->color4f[0][0] = c0[0];
11712 decal->color4f[0][1] = c0[1];
11713 decal->color4f[0][2] = c0[2];
11714 decal->color4f[0][3] = 1;
11715 decal->color4f[1][0] = c1[0];
11716 decal->color4f[1][1] = c1[1];
11717 decal->color4f[1][2] = c1[2];
11718 decal->color4f[1][3] = 1;
11719 decal->color4f[2][0] = c2[0];
11720 decal->color4f[2][1] = c2[1];
11721 decal->color4f[2][2] = c2[2];
11722 decal->color4f[2][3] = 1;
11723 decal->vertex3f[0][0] = v0[0];
11724 decal->vertex3f[0][1] = v0[1];
11725 decal->vertex3f[0][2] = v0[2];
11726 decal->vertex3f[1][0] = v1[0];
11727 decal->vertex3f[1][1] = v1[1];
11728 decal->vertex3f[1][2] = v1[2];
11729 decal->vertex3f[2][0] = v2[0];
11730 decal->vertex3f[2][1] = v2[1];
11731 decal->vertex3f[2][2] = v2[2];
11732 decal->texcoord2f[0][0] = t0[0];
11733 decal->texcoord2f[0][1] = t0[1];
11734 decal->texcoord2f[1][0] = t1[0];
11735 decal->texcoord2f[1][1] = t1[1];
11736 decal->texcoord2f[2][0] = t2[0];
11737 decal->texcoord2f[2][1] = t2[1];
11738 TriangleNormal(v0, v1, v2, decal->plane);
11739 VectorNormalize(decal->plane);
11740 decal->plane[3] = DotProduct(v0, decal->plane);
11743 extern cvar_t cl_decals_bias;
11744 extern cvar_t cl_decals_models;
11745 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11746 // baseparms, parms, temps
11747 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)
11752 const float *vertex3f;
11753 const float *normal3f;
11755 float points[2][9][3];
11762 e = rsurface.modelelement3i + 3*triangleindex;
11764 vertex3f = rsurface.modelvertex3f;
11765 normal3f = rsurface.modelnormal3f;
11769 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11771 index = 3*e[cornerindex];
11772 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11777 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11779 index = 3*e[cornerindex];
11780 VectorCopy(vertex3f + index, v[cornerindex]);
11785 //TriangleNormal(v[0], v[1], v[2], normal);
11786 //if (DotProduct(normal, localnormal) < 0.0f)
11788 // clip by each of the box planes formed from the projection matrix
11789 // if anything survives, we emit the decal
11790 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]);
11793 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]);
11796 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]);
11799 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]);
11802 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]);
11805 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]);
11808 // some part of the triangle survived, so we have to accept it...
11811 // dynamic always uses the original triangle
11813 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11815 index = 3*e[cornerindex];
11816 VectorCopy(vertex3f + index, v[cornerindex]);
11819 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11821 // convert vertex positions to texcoords
11822 Matrix4x4_Transform(projection, v[cornerindex], temp);
11823 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11824 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11825 // calculate distance fade from the projection origin
11826 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11827 f = bound(0.0f, f, 1.0f);
11828 c[cornerindex][0] = r * f;
11829 c[cornerindex][1] = g * f;
11830 c[cornerindex][2] = b * f;
11831 c[cornerindex][3] = 1.0f;
11832 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11835 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);
11837 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11838 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);
11840 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)
11842 matrix4x4_t projection;
11843 decalsystem_t *decalsystem;
11846 const msurface_t *surface;
11847 const msurface_t *surfaces;
11848 const int *surfacelist;
11849 const texture_t *texture;
11851 int numsurfacelist;
11852 int surfacelistindex;
11855 float localorigin[3];
11856 float localnormal[3];
11857 float localmins[3];
11858 float localmaxs[3];
11861 float planes[6][4];
11864 int bih_triangles_count;
11865 int bih_triangles[256];
11866 int bih_surfaces[256];
11868 decalsystem = &ent->decalsystem;
11869 model = ent->model;
11870 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11872 R_DecalSystem_Reset(&ent->decalsystem);
11876 if (!model->brush.data_leafs && !cl_decals_models.integer)
11878 if (decalsystem->model)
11879 R_DecalSystem_Reset(decalsystem);
11883 if (decalsystem->model != model)
11884 R_DecalSystem_Reset(decalsystem);
11885 decalsystem->model = model;
11887 RSurf_ActiveModelEntity(ent, true, false, false);
11889 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11890 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11891 VectorNormalize(localnormal);
11892 localsize = worldsize*rsurface.inversematrixscale;
11893 localmins[0] = localorigin[0] - localsize;
11894 localmins[1] = localorigin[1] - localsize;
11895 localmins[2] = localorigin[2] - localsize;
11896 localmaxs[0] = localorigin[0] + localsize;
11897 localmaxs[1] = localorigin[1] + localsize;
11898 localmaxs[2] = localorigin[2] + localsize;
11900 //VectorCopy(localnormal, planes[4]);
11901 //VectorVectors(planes[4], planes[2], planes[0]);
11902 AnglesFromVectors(angles, localnormal, NULL, false);
11903 AngleVectors(angles, planes[0], planes[2], planes[4]);
11904 VectorNegate(planes[0], planes[1]);
11905 VectorNegate(planes[2], planes[3]);
11906 VectorNegate(planes[4], planes[5]);
11907 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11908 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11909 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11910 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11911 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11912 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11917 matrix4x4_t forwardprojection;
11918 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11919 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11924 float projectionvector[4][3];
11925 VectorScale(planes[0], ilocalsize, projectionvector[0]);
11926 VectorScale(planes[2], ilocalsize, projectionvector[1]);
11927 VectorScale(planes[4], ilocalsize, projectionvector[2]);
11928 projectionvector[0][0] = planes[0][0] * ilocalsize;
11929 projectionvector[0][1] = planes[1][0] * ilocalsize;
11930 projectionvector[0][2] = planes[2][0] * ilocalsize;
11931 projectionvector[1][0] = planes[0][1] * ilocalsize;
11932 projectionvector[1][1] = planes[1][1] * ilocalsize;
11933 projectionvector[1][2] = planes[2][1] * ilocalsize;
11934 projectionvector[2][0] = planes[0][2] * ilocalsize;
11935 projectionvector[2][1] = planes[1][2] * ilocalsize;
11936 projectionvector[2][2] = planes[2][2] * ilocalsize;
11937 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11938 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11939 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11940 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11944 dynamic = model->surfmesh.isanimated;
11945 numsurfacelist = model->nummodelsurfaces;
11946 surfacelist = model->sortedmodelsurfaces;
11947 surfaces = model->data_surfaces;
11950 bih_triangles_count = -1;
11953 if(model->render_bih.numleafs)
11954 bih = &model->render_bih;
11955 else if(model->collision_bih.numleafs)
11956 bih = &model->collision_bih;
11959 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11960 if(bih_triangles_count == 0)
11962 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11964 if(bih_triangles_count > 0)
11966 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11968 surfaceindex = bih_surfaces[triangleindex];
11969 surface = surfaces + surfaceindex;
11970 texture = surface->texture;
11971 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11973 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11975 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11980 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11982 surfaceindex = surfacelist[surfacelistindex];
11983 surface = surfaces + surfaceindex;
11984 // check cull box first because it rejects more than any other check
11985 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11987 // skip transparent surfaces
11988 texture = surface->texture;
11989 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11991 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11993 numtriangles = surface->num_triangles;
11994 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11995 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
12000 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
12001 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)
12003 int renderentityindex;
12004 float worldmins[3];
12005 float worldmaxs[3];
12006 entity_render_t *ent;
12008 if (!cl_decals_newsystem.integer)
12011 worldmins[0] = worldorigin[0] - worldsize;
12012 worldmins[1] = worldorigin[1] - worldsize;
12013 worldmins[2] = worldorigin[2] - worldsize;
12014 worldmaxs[0] = worldorigin[0] + worldsize;
12015 worldmaxs[1] = worldorigin[1] + worldsize;
12016 worldmaxs[2] = worldorigin[2] + worldsize;
12018 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12020 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
12022 ent = r_refdef.scene.entities[renderentityindex];
12023 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
12026 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12030 typedef struct r_decalsystem_splatqueue_s
12032 vec3_t worldorigin;
12033 vec3_t worldnormal;
12037 unsigned int decalsequence;
12039 r_decalsystem_splatqueue_t;
12041 int r_decalsystem_numqueued = 0;
12042 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
12044 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)
12046 r_decalsystem_splatqueue_t *queue;
12048 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
12051 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
12052 VectorCopy(worldorigin, queue->worldorigin);
12053 VectorCopy(worldnormal, queue->worldnormal);
12054 Vector4Set(queue->color, r, g, b, a);
12055 Vector4Set(queue->tcrange, s1, t1, s2, t2);
12056 queue->worldsize = worldsize;
12057 queue->decalsequence = cl.decalsequence++;
12060 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
12063 r_decalsystem_splatqueue_t *queue;
12065 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
12066 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);
12067 r_decalsystem_numqueued = 0;
12070 extern cvar_t cl_decals_max;
12071 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12074 decalsystem_t *decalsystem = &ent->decalsystem;
12076 unsigned int killsequence;
12081 if (!decalsystem->numdecals)
12084 if (r_showsurfaces.integer)
12087 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12089 R_DecalSystem_Reset(decalsystem);
12093 killsequence = cl.decalsequence - bound(1, (unsigned int) cl_decals_max.integer, cl.decalsequence);
12094 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12096 if (decalsystem->lastupdatetime)
12097 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
12100 decalsystem->lastupdatetime = r_refdef.scene.time;
12101 numdecals = decalsystem->numdecals;
12103 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12105 if (decal->color4f[0][3])
12107 decal->lived += frametime;
12108 if (killsequence > decal->decalsequence || decal->lived >= lifetime)
12110 memset(decal, 0, sizeof(*decal));
12111 if (decalsystem->freedecal > i)
12112 decalsystem->freedecal = i;
12116 decal = decalsystem->decals;
12117 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
12120 // collapse the array by shuffling the tail decals into the gaps
12123 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
12124 decalsystem->freedecal++;
12125 if (decalsystem->freedecal == numdecals)
12127 decal[decalsystem->freedecal] = decal[--numdecals];
12130 decalsystem->numdecals = numdecals;
12132 if (numdecals <= 0)
12134 // if there are no decals left, reset decalsystem
12135 R_DecalSystem_Reset(decalsystem);
12139 extern skinframe_t *decalskinframe;
12140 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12143 decalsystem_t *decalsystem = &ent->decalsystem;
12152 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12155 numdecals = decalsystem->numdecals;
12159 if (r_showsurfaces.integer)
12162 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12164 R_DecalSystem_Reset(decalsystem);
12168 // if the model is static it doesn't matter what value we give for
12169 // wantnormals and wanttangents, so this logic uses only rules applicable
12170 // to a model, knowing that they are meaningless otherwise
12171 if (ent == r_refdef.scene.worldentity)
12172 RSurf_ActiveWorldEntity();
12174 RSurf_ActiveModelEntity(ent, false, false, false);
12176 decalsystem->lastupdatetime = r_refdef.scene.time;
12178 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12180 // update vertex positions for animated models
12181 v3f = decalsystem->vertex3f;
12182 c4f = decalsystem->color4f;
12183 t2f = decalsystem->texcoord2f;
12184 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12186 if (!decal->color4f[0][3])
12189 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12193 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
12196 // update color values for fading decals
12197 if (decal->lived >= cl_decals_time.value)
12198 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12202 c4f[ 0] = decal->color4f[0][0] * alpha;
12203 c4f[ 1] = decal->color4f[0][1] * alpha;
12204 c4f[ 2] = decal->color4f[0][2] * alpha;
12206 c4f[ 4] = decal->color4f[1][0] * alpha;
12207 c4f[ 5] = decal->color4f[1][1] * alpha;
12208 c4f[ 6] = decal->color4f[1][2] * alpha;
12210 c4f[ 8] = decal->color4f[2][0] * alpha;
12211 c4f[ 9] = decal->color4f[2][1] * alpha;
12212 c4f[10] = decal->color4f[2][2] * alpha;
12215 t2f[0] = decal->texcoord2f[0][0];
12216 t2f[1] = decal->texcoord2f[0][1];
12217 t2f[2] = decal->texcoord2f[1][0];
12218 t2f[3] = decal->texcoord2f[1][1];
12219 t2f[4] = decal->texcoord2f[2][0];
12220 t2f[5] = decal->texcoord2f[2][1];
12222 // update vertex positions for animated models
12223 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12225 e = rsurface.modelelement3i + 3*decal->triangleindex;
12226 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12227 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12228 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12232 VectorCopy(decal->vertex3f[0], v3f);
12233 VectorCopy(decal->vertex3f[1], v3f + 3);
12234 VectorCopy(decal->vertex3f[2], v3f + 6);
12237 if (r_refdef.fogenabled)
12239 alpha = RSurf_FogVertex(v3f);
12240 VectorScale(c4f, alpha, c4f);
12241 alpha = RSurf_FogVertex(v3f + 3);
12242 VectorScale(c4f + 4, alpha, c4f + 4);
12243 alpha = RSurf_FogVertex(v3f + 6);
12244 VectorScale(c4f + 8, alpha, c4f + 8);
12255 r_refdef.stats[r_stat_drawndecals] += numtris;
12257 // now render the decals all at once
12258 // (this assumes they all use one particle font texture!)
12259 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);
12260 // R_Mesh_ResetTextureState();
12261 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12262 GL_DepthMask(false);
12263 GL_DepthRange(0, 1);
12264 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12265 GL_DepthTest(true);
12266 GL_CullFace(GL_NONE);
12267 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12268 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12269 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12273 static void R_DrawModelDecals(void)
12277 // fade faster when there are too many decals
12278 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12279 for (i = 0;i < r_refdef.scene.numentities;i++)
12280 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12282 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12283 for (i = 0;i < r_refdef.scene.numentities;i++)
12284 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12285 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12287 R_DecalSystem_ApplySplatEntitiesQueue();
12289 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12290 for (i = 0;i < r_refdef.scene.numentities;i++)
12291 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12293 r_refdef.stats[r_stat_totaldecals] += numdecals;
12295 if (r_showsurfaces.integer)
12298 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12300 for (i = 0;i < r_refdef.scene.numentities;i++)
12302 if (!r_refdef.viewcache.entityvisible[i])
12304 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12305 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12309 extern cvar_t mod_collision_bih;
12310 static void R_DrawDebugModel(void)
12312 entity_render_t *ent = rsurface.entity;
12313 int i, j, flagsmask;
12314 const msurface_t *surface;
12315 dp_model_t *model = ent->model;
12317 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12320 if (r_showoverdraw.value > 0)
12322 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12323 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12324 R_SetupShader_Generic_NoTexture(false, false);
12325 GL_DepthTest(false);
12326 GL_DepthMask(false);
12327 GL_DepthRange(0, 1);
12328 GL_BlendFunc(GL_ONE, GL_ONE);
12329 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12331 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12333 rsurface.texture = R_GetCurrentTexture(surface->texture);
12334 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12336 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12337 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12338 if (!rsurface.texture->currentlayers->depthmask)
12339 GL_Color(c, 0, 0, 1.0f);
12340 else if (ent == r_refdef.scene.worldentity)
12341 GL_Color(c, c, c, 1.0f);
12343 GL_Color(0, c, 0, 1.0f);
12344 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12348 rsurface.texture = NULL;
12351 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12353 // R_Mesh_ResetTextureState();
12354 R_SetupShader_Generic_NoTexture(false, false);
12355 GL_DepthRange(0, 1);
12356 GL_DepthTest(!r_showdisabledepthtest.integer);
12357 GL_DepthMask(false);
12358 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12360 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12364 qboolean cullbox = false;
12365 const q3mbrush_t *brush;
12366 const bih_t *bih = &model->collision_bih;
12367 const bih_leaf_t *bihleaf;
12368 float vertex3f[3][3];
12369 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12370 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12372 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12374 switch (bihleaf->type)
12377 brush = model->brush.data_brushes + bihleaf->itemindex;
12378 if (brush->colbrushf && brush->colbrushf->numtriangles)
12380 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);
12381 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12382 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12385 case BIH_COLLISIONTRIANGLE:
12386 triangleindex = bihleaf->itemindex;
12387 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12388 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12389 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12390 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);
12391 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12392 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12394 case BIH_RENDERTRIANGLE:
12395 triangleindex = bihleaf->itemindex;
12396 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12397 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12398 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12399 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);
12400 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12401 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12407 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12410 if (r_showtris.integer && qglPolygonMode)
12412 if (r_showdisabledepthtest.integer)
12414 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12415 GL_DepthMask(false);
12419 GL_BlendFunc(GL_ONE, GL_ZERO);
12420 GL_DepthMask(true);
12422 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12423 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12425 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12427 rsurface.texture = R_GetCurrentTexture(surface->texture);
12428 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12430 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12431 if (!rsurface.texture->currentlayers->depthmask)
12432 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12433 else if (ent == r_refdef.scene.worldentity)
12434 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12436 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12437 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12441 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12442 rsurface.texture = NULL;
12445 if (r_shownormals.value != 0 && qglBegin)
12449 if (r_showdisabledepthtest.integer)
12451 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12452 GL_DepthMask(false);
12456 GL_BlendFunc(GL_ONE, GL_ZERO);
12457 GL_DepthMask(true);
12459 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12461 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12463 rsurface.texture = R_GetCurrentTexture(surface->texture);
12464 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12466 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12467 qglBegin(GL_LINES);
12468 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12470 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12472 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12473 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12474 qglVertex3f(v[0], v[1], v[2]);
12475 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12476 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12477 qglVertex3f(v[0], v[1], v[2]);
12480 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12482 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12484 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12485 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12486 qglVertex3f(v[0], v[1], v[2]);
12487 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12488 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12489 qglVertex3f(v[0], v[1], v[2]);
12492 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12494 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12496 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12497 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12498 qglVertex3f(v[0], v[1], v[2]);
12499 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12500 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12501 qglVertex3f(v[0], v[1], v[2]);
12504 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12506 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12508 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12509 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12510 qglVertex3f(v[0], v[1], v[2]);
12511 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12512 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12513 qglVertex3f(v[0], v[1], v[2]);
12520 rsurface.texture = NULL;
12525 int r_maxsurfacelist = 0;
12526 const msurface_t **r_surfacelist = NULL;
12527 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12529 int i, j, endj, flagsmask;
12530 dp_model_t *model = r_refdef.scene.worldmodel;
12531 msurface_t *surfaces;
12532 unsigned char *update;
12533 int numsurfacelist = 0;
12537 if (r_maxsurfacelist < model->num_surfaces)
12539 r_maxsurfacelist = model->num_surfaces;
12541 Mem_Free((msurface_t**)r_surfacelist);
12542 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12545 RSurf_ActiveWorldEntity();
12547 surfaces = model->data_surfaces;
12548 update = model->brushq1.lightmapupdateflags;
12550 // update light styles on this submodel
12551 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12553 model_brush_lightstyleinfo_t *style;
12554 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12556 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12558 int *list = style->surfacelist;
12559 style->value = r_refdef.scene.lightstylevalue[style->style];
12560 for (j = 0;j < style->numsurfaces;j++)
12561 update[list[j]] = true;
12566 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12570 R_DrawDebugModel();
12571 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12575 rsurface.lightmaptexture = NULL;
12576 rsurface.deluxemaptexture = NULL;
12577 rsurface.uselightmaptexture = false;
12578 rsurface.texture = NULL;
12579 rsurface.rtlight = NULL;
12580 numsurfacelist = 0;
12581 // add visible surfaces to draw list
12582 for (i = 0;i < model->nummodelsurfaces;i++)
12584 j = model->sortedmodelsurfaces[i];
12585 if (r_refdef.viewcache.world_surfacevisible[j])
12586 r_surfacelist[numsurfacelist++] = surfaces + j;
12588 // update lightmaps if needed
12589 if (model->brushq1.firstrender)
12591 model->brushq1.firstrender = false;
12592 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12594 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12598 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12599 if (r_refdef.viewcache.world_surfacevisible[j])
12601 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12603 // don't do anything if there were no surfaces
12604 if (!numsurfacelist)
12606 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12609 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12611 // add to stats if desired
12612 if (r_speeds.integer && !skysurfaces && !depthonly)
12614 r_refdef.stats[r_stat_world_surfaces] += numsurfacelist;
12615 for (j = 0;j < numsurfacelist;j++)
12616 r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles;
12619 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12622 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12624 int i, j, endj, flagsmask;
12625 dp_model_t *model = ent->model;
12626 msurface_t *surfaces;
12627 unsigned char *update;
12628 int numsurfacelist = 0;
12632 if (r_maxsurfacelist < model->num_surfaces)
12634 r_maxsurfacelist = model->num_surfaces;
12636 Mem_Free((msurface_t **)r_surfacelist);
12637 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12640 // if the model is static it doesn't matter what value we give for
12641 // wantnormals and wanttangents, so this logic uses only rules applicable
12642 // to a model, knowing that they are meaningless otherwise
12643 if (ent == r_refdef.scene.worldentity)
12644 RSurf_ActiveWorldEntity();
12645 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12646 RSurf_ActiveModelEntity(ent, false, false, false);
12648 RSurf_ActiveModelEntity(ent, true, true, true);
12649 else if (depthonly)
12651 switch (vid.renderpath)
12653 case RENDERPATH_GL20:
12654 case RENDERPATH_D3D9:
12655 case RENDERPATH_D3D10:
12656 case RENDERPATH_D3D11:
12657 case RENDERPATH_SOFT:
12658 case RENDERPATH_GLES2:
12659 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12661 case RENDERPATH_GL11:
12662 case RENDERPATH_GL13:
12663 case RENDERPATH_GLES1:
12664 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12670 switch (vid.renderpath)
12672 case RENDERPATH_GL20:
12673 case RENDERPATH_D3D9:
12674 case RENDERPATH_D3D10:
12675 case RENDERPATH_D3D11:
12676 case RENDERPATH_SOFT:
12677 case RENDERPATH_GLES2:
12678 RSurf_ActiveModelEntity(ent, true, true, false);
12680 case RENDERPATH_GL11:
12681 case RENDERPATH_GL13:
12682 case RENDERPATH_GLES1:
12683 RSurf_ActiveModelEntity(ent, true, false, false);
12688 surfaces = model->data_surfaces;
12689 update = model->brushq1.lightmapupdateflags;
12691 // update light styles
12692 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12694 model_brush_lightstyleinfo_t *style;
12695 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12697 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12699 int *list = style->surfacelist;
12700 style->value = r_refdef.scene.lightstylevalue[style->style];
12701 for (j = 0;j < style->numsurfaces;j++)
12702 update[list[j]] = true;
12707 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12711 R_DrawDebugModel();
12712 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12716 rsurface.lightmaptexture = NULL;
12717 rsurface.deluxemaptexture = NULL;
12718 rsurface.uselightmaptexture = false;
12719 rsurface.texture = NULL;
12720 rsurface.rtlight = NULL;
12721 numsurfacelist = 0;
12722 // add visible surfaces to draw list
12723 for (i = 0;i < model->nummodelsurfaces;i++)
12724 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12725 // don't do anything if there were no surfaces
12726 if (!numsurfacelist)
12728 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12731 // update lightmaps if needed
12735 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12740 R_BuildLightMap(ent, surfaces + j);
12745 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12747 // add to stats if desired
12748 if (r_speeds.integer && !skysurfaces && !depthonly)
12750 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12751 for (j = 0;j < numsurfacelist;j++)
12752 r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12755 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12758 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12760 static texture_t texture;
12761 static msurface_t surface;
12762 const msurface_t *surfacelist = &surface;
12764 // fake enough texture and surface state to render this geometry
12766 texture.update_lastrenderframe = -1; // regenerate this texture
12767 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12768 texture.basealpha = 1.0f;
12769 texture.currentskinframe = skinframe;
12770 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12771 texture.offsetmapping = OFFSETMAPPING_OFF;
12772 texture.offsetscale = 1;
12773 texture.specularscalemod = 1;
12774 texture.specularpowermod = 1;
12775 texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12776 // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12777 // JUST GREP FOR "specularscalemod = 1".
12779 surface.texture = &texture;
12780 surface.num_triangles = numtriangles;
12781 surface.num_firsttriangle = firsttriangle;
12782 surface.num_vertices = numvertices;
12783 surface.num_firstvertex = firstvertex;
12786 rsurface.texture = R_GetCurrentTexture(surface.texture);
12787 rsurface.lightmaptexture = NULL;
12788 rsurface.deluxemaptexture = NULL;
12789 rsurface.uselightmaptexture = false;
12790 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12793 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)
12795 static msurface_t surface;
12796 const msurface_t *surfacelist = &surface;
12798 // fake enough texture and surface state to render this geometry
12799 surface.texture = texture;
12800 surface.num_triangles = numtriangles;
12801 surface.num_firsttriangle = firsttriangle;
12802 surface.num_vertices = numvertices;
12803 surface.num_firstvertex = firstvertex;
12806 rsurface.texture = R_GetCurrentTexture(surface.texture);
12807 rsurface.lightmaptexture = NULL;
12808 rsurface.deluxemaptexture = NULL;
12809 rsurface.uselightmaptexture = false;
12810 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);