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 //=======================================================================================================================================================
642 typedef struct shaderpermutationinfo_s
647 shaderpermutationinfo_t;
649 typedef struct shadermodeinfo_s
651 const char *sourcebasename;
652 const char *extension;
653 const char **builtinshaderstrings;
662 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
663 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
665 {"#define USEDIFFUSE\n", " diffuse"},
666 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
667 {"#define USEVIEWTINT\n", " viewtint"},
668 {"#define USECOLORMAPPING\n", " colormapping"},
669 {"#define USESATURATION\n", " saturation"},
670 {"#define USEFOGINSIDE\n", " foginside"},
671 {"#define USEFOGOUTSIDE\n", " fogoutside"},
672 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
673 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
674 {"#define USEGAMMARAMPS\n", " gammaramps"},
675 {"#define USECUBEFILTER\n", " cubefilter"},
676 {"#define USEGLOW\n", " glow"},
677 {"#define USEBLOOM\n", " bloom"},
678 {"#define USESPECULAR\n", " specular"},
679 {"#define USEPOSTPROCESSING\n", " postprocessing"},
680 {"#define USEREFLECTION\n", " reflection"},
681 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
682 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
683 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
684 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
685 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
686 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
687 {"#define USEALPHAKILL\n", " alphakill"},
688 {"#define USEREFLECTCUBE\n", " reflectcube"},
689 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
690 {"#define USEBOUNCEGRID\n", " bouncegrid"},
691 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
692 {"#define USETRIPPY\n", " trippy"},
693 {"#define USEDEPTHRGB\n", " depthrgb"},
694 {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
695 {"#define USESKELETAL\n", " skeletal"},
696 {"#define USEOCCLUDE\n", " occlude"}
699 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
700 shadermodeinfo_t shadermodeinfo[SHADERLANGUAGE_COUNT][SHADERMODE_COUNT] =
702 // SHADERLANGUAGE_GLSL
704 {"combined", "glsl", builtinshaderstrings, "#define MODE_GENERIC\n", " generic"},
705 {"combined", "glsl", builtinshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
706 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
707 {"combined", "glsl", builtinshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
708 {"combined", "glsl", builtinshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
709 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
710 {"combined", "glsl", builtinshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
711 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
712 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
713 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
714 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
715 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
716 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
717 {"combined", "glsl", builtinshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
718 {"combined", "glsl", builtinshaderstrings, "#define MODE_WATER\n", " water"},
719 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
720 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
722 // SHADERLANGUAGE_HLSL
724 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_GENERIC\n", " generic"},
725 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
726 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
727 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
728 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
729 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
730 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
731 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
732 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
733 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
734 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
735 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
736 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
737 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
738 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_WATER\n", " water"},
739 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
740 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
744 struct r_glsl_permutation_s;
745 typedef struct r_glsl_permutation_s
748 struct r_glsl_permutation_s *hashnext;
750 unsigned int permutation;
752 /// indicates if we have tried compiling this permutation already
754 /// 0 if compilation failed
756 // texture units assigned to each detected uniform
757 int tex_Texture_First;
758 int tex_Texture_Second;
759 int tex_Texture_GammaRamps;
760 int tex_Texture_Normal;
761 int tex_Texture_Color;
762 int tex_Texture_Gloss;
763 int tex_Texture_Glow;
764 int tex_Texture_SecondaryNormal;
765 int tex_Texture_SecondaryColor;
766 int tex_Texture_SecondaryGloss;
767 int tex_Texture_SecondaryGlow;
768 int tex_Texture_Pants;
769 int tex_Texture_Shirt;
770 int tex_Texture_FogHeightTexture;
771 int tex_Texture_FogMask;
772 int tex_Texture_Lightmap;
773 int tex_Texture_Deluxemap;
774 int tex_Texture_Attenuation;
775 int tex_Texture_Cube;
776 int tex_Texture_Refraction;
777 int tex_Texture_Reflection;
778 int tex_Texture_ShadowMap2D;
779 int tex_Texture_CubeProjection;
780 int tex_Texture_ScreenNormalMap;
781 int tex_Texture_ScreenDiffuse;
782 int tex_Texture_ScreenSpecular;
783 int tex_Texture_ReflectMask;
784 int tex_Texture_ReflectCube;
785 int tex_Texture_BounceGrid;
786 /// locations of detected uniforms in program object, or -1 if not found
787 int loc_Texture_First;
788 int loc_Texture_Second;
789 int loc_Texture_GammaRamps;
790 int loc_Texture_Normal;
791 int loc_Texture_Color;
792 int loc_Texture_Gloss;
793 int loc_Texture_Glow;
794 int loc_Texture_SecondaryNormal;
795 int loc_Texture_SecondaryColor;
796 int loc_Texture_SecondaryGloss;
797 int loc_Texture_SecondaryGlow;
798 int loc_Texture_Pants;
799 int loc_Texture_Shirt;
800 int loc_Texture_FogHeightTexture;
801 int loc_Texture_FogMask;
802 int loc_Texture_Lightmap;
803 int loc_Texture_Deluxemap;
804 int loc_Texture_Attenuation;
805 int loc_Texture_Cube;
806 int loc_Texture_Refraction;
807 int loc_Texture_Reflection;
808 int loc_Texture_ShadowMap2D;
809 int loc_Texture_CubeProjection;
810 int loc_Texture_ScreenNormalMap;
811 int loc_Texture_ScreenDiffuse;
812 int loc_Texture_ScreenSpecular;
813 int loc_Texture_ReflectMask;
814 int loc_Texture_ReflectCube;
815 int loc_Texture_BounceGrid;
817 int loc_BloomBlur_Parameters;
819 int loc_Color_Ambient;
820 int loc_Color_Diffuse;
821 int loc_Color_Specular;
825 int loc_DeferredColor_Ambient;
826 int loc_DeferredColor_Diffuse;
827 int loc_DeferredColor_Specular;
828 int loc_DeferredMod_Diffuse;
829 int loc_DeferredMod_Specular;
830 int loc_DistortScaleRefractReflect;
833 int loc_FogHeightFade;
835 int loc_FogPlaneViewDist;
836 int loc_FogRangeRecip;
839 int loc_LightPosition;
840 int loc_OffsetMapping_ScaleSteps;
841 int loc_OffsetMapping_LodDistance;
842 int loc_OffsetMapping_Bias;
844 int loc_ReflectColor;
845 int loc_ReflectFactor;
846 int loc_ReflectOffset;
847 int loc_RefractColor;
849 int loc_ScreenCenterRefractReflect;
850 int loc_ScreenScaleRefractReflect;
851 int loc_ScreenToDepth;
852 int loc_ShadowMap_Parameters;
853 int loc_ShadowMap_TextureScale;
854 int loc_SpecularPower;
855 int loc_Skeletal_Transform12;
860 int loc_ViewTintColor;
862 int loc_ModelToLight;
864 int loc_BackgroundTexMatrix;
865 int loc_ModelViewProjectionMatrix;
866 int loc_ModelViewMatrix;
867 int loc_PixelToScreenTexCoord;
868 int loc_ModelToReflectCube;
869 int loc_ShadowMapMatrix;
870 int loc_BloomColorSubtract;
871 int loc_NormalmapScrollBlend;
872 int loc_BounceGridMatrix;
873 int loc_BounceGridIntensity;
874 /// uniform block bindings
875 int ubibind_Skeletal_Transform12_UniformBlock;
876 /// uniform block indices
877 int ubiloc_Skeletal_Transform12_UniformBlock;
879 r_glsl_permutation_t;
881 #define SHADERPERMUTATION_HASHSIZE 256
884 // non-degradable "lightweight" shader parameters to keep the permutations simpler
885 // these can NOT degrade! only use for simple stuff
888 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
889 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
890 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
891 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
892 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
893 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
894 SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
895 SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7, ///< LOD for offsetmapping
896 SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
897 SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
898 SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
899 SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
900 SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
901 SHADERSTATICPARM_FXAA = 13 ///< fast approximate anti aliasing
903 #define SHADERSTATICPARMS_COUNT 14
905 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
906 static int shaderstaticparms_count = 0;
908 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
909 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
911 extern qboolean r_shadow_shadowmapsampler;
912 extern int r_shadow_shadowmappcf;
913 qboolean R_CompileShader_CheckStaticParms(void)
915 static int r_compileshader_staticparms_save[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5];
916 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
917 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
920 if (r_glsl_saturation_redcompensate.integer)
921 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
922 if (r_glsl_vertextextureblend_usebothalphas.integer)
923 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
924 if (r_shadow_glossexact.integer)
925 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
926 if (r_glsl_postprocess.integer)
928 if (r_glsl_postprocess_uservec1_enable.integer)
929 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
930 if (r_glsl_postprocess_uservec2_enable.integer)
931 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
932 if (r_glsl_postprocess_uservec3_enable.integer)
933 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
934 if (r_glsl_postprocess_uservec4_enable.integer)
935 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
938 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_FXAA);
939 if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
940 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
942 if (r_shadow_shadowmapsampler)
943 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
944 if (r_shadow_shadowmappcf > 1)
945 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
946 else if (r_shadow_shadowmappcf)
947 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
948 if (r_celshading.integer)
949 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
950 if (r_celoutlines.integer)
951 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
953 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
956 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
957 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
958 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
960 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
961 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
963 shaderstaticparms_count = 0;
966 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
967 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
968 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
969 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
970 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
971 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
972 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
973 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
974 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
975 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
976 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
977 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
978 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
979 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_FXAA, "USEFXAA");
982 /// information about each possible shader permutation
983 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
984 /// currently selected permutation
985 r_glsl_permutation_t *r_glsl_permutation;
986 /// storage for permutations linked in the hash table
987 memexpandablearray_t r_glsl_permutationarray;
989 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
991 //unsigned int hashdepth = 0;
992 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
993 r_glsl_permutation_t *p;
994 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
996 if (p->mode == mode && p->permutation == permutation)
998 //if (hashdepth > 10)
999 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1004 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1006 p->permutation = permutation;
1007 p->hashnext = r_glsl_permutationhash[mode][hashindex];
1008 r_glsl_permutationhash[mode][hashindex] = p;
1009 //if (hashdepth > 10)
1010 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1014 static char *R_ShaderStrCat(const char **strings)
1017 const char **p = strings;
1020 for (p = strings;(t = *p);p++)
1023 s = string = (char *)Mem_Alloc(r_main_mempool, len);
1025 for (p = strings;(t = *p);p++)
1035 static char *R_ShaderStrCat(const char **strings);
1036 static void R_InitShaderModeInfo(void)
1039 shadermodeinfo_t *modeinfo;
1040 // we have a bunch of things to compute that weren't calculated at engine compile time - all filenames should have a crc of the builtin strings to prevent accidental overrides (any customization must be updated to match engine)
1041 for (language = 0; language < SHADERLANGUAGE_COUNT; language++)
1043 for (i = 0; i < SHADERMODE_COUNT; i++)
1045 char filename[MAX_QPATH];
1046 modeinfo = &shadermodeinfo[language][i];
1047 modeinfo->builtinstring = R_ShaderStrCat(modeinfo->builtinshaderstrings);
1048 modeinfo->builtincrc = CRC_Block((const unsigned char *)modeinfo->builtinstring, strlen(modeinfo->builtinstring));
1049 dpsnprintf(filename, sizeof(filename), "%s/%s_crc%i.%s", modeinfo->extension, modeinfo->sourcebasename, modeinfo->builtincrc, modeinfo->extension);
1050 modeinfo->filename = Mem_strdup(r_main_mempool, filename);
1055 static char *ShaderModeInfo_GetShaderText(shadermodeinfo_t *modeinfo, qboolean printfromdisknotice, qboolean builtinonly)
1058 // if the mode has no filename we have to return the builtin string
1059 if (builtinonly || !modeinfo->filename)
1060 return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1061 // note that FS_LoadFile appends a 0 byte to make it a valid string
1062 shaderstring = (char *)FS_LoadFile(modeinfo->filename, r_main_mempool, false, NULL);
1065 if (printfromdisknotice)
1066 Con_DPrintf("Loading shaders from file %s...\n", modeinfo->filename);
1067 return shaderstring;
1069 // fall back to builtinstring
1070 return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1073 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1078 shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_GLSL][mode];
1080 char permutationname[256];
1081 int vertstrings_count = 0;
1082 int geomstrings_count = 0;
1083 int fragstrings_count = 0;
1084 const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1085 const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1086 const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1093 permutationname[0] = 0;
1094 sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1096 strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1098 // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1099 if(vid.support.glshaderversion >= 140)
1101 vertstrings_list[vertstrings_count++] = "#version 140\n";
1102 geomstrings_list[geomstrings_count++] = "#version 140\n";
1103 fragstrings_list[fragstrings_count++] = "#version 140\n";
1104 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1105 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1106 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1108 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1109 else if(vid.support.glshaderversion >= 130)
1111 vertstrings_list[vertstrings_count++] = "#version 130\n";
1112 geomstrings_list[geomstrings_count++] = "#version 130\n";
1113 fragstrings_list[fragstrings_count++] = "#version 130\n";
1114 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1115 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1116 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1118 // if we can do #version 120, we should (this adds the invariant keyword)
1119 else if(vid.support.glshaderversion >= 120)
1121 vertstrings_list[vertstrings_count++] = "#version 120\n";
1122 geomstrings_list[geomstrings_count++] = "#version 120\n";
1123 fragstrings_list[fragstrings_count++] = "#version 120\n";
1124 vertstrings_list[vertstrings_count++] = "#define GLSL120\n";
1125 geomstrings_list[geomstrings_count++] = "#define GLSL120\n";
1126 fragstrings_list[fragstrings_count++] = "#define GLSL120\n";
1128 // GLES also adds several things from GLSL120
1129 switch(vid.renderpath)
1131 case RENDERPATH_GLES2:
1132 vertstrings_list[vertstrings_count++] = "#define GLES\n";
1133 geomstrings_list[geomstrings_count++] = "#define GLES\n";
1134 fragstrings_list[fragstrings_count++] = "#define GLES\n";
1140 // the first pretext is which type of shader to compile as
1141 // (later these will all be bound together as a program object)
1142 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1143 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1144 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1146 // the second pretext is the mode (for example a light source)
1147 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1148 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1149 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1150 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1152 // now add all the permutation pretexts
1153 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1155 if (permutation & (1<<i))
1157 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1158 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1159 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1160 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1164 // keep line numbers correct
1165 vertstrings_list[vertstrings_count++] = "\n";
1166 geomstrings_list[geomstrings_count++] = "\n";
1167 fragstrings_list[fragstrings_count++] = "\n";
1172 R_CompileShader_AddStaticParms(mode, permutation);
1173 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1174 vertstrings_count += shaderstaticparms_count;
1175 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1176 geomstrings_count += shaderstaticparms_count;
1177 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1178 fragstrings_count += shaderstaticparms_count;
1180 // now append the shader text itself
1181 vertstrings_list[vertstrings_count++] = sourcestring;
1182 geomstrings_list[geomstrings_count++] = sourcestring;
1183 fragstrings_list[fragstrings_count++] = sourcestring;
1185 // compile the shader program
1186 if (vertstrings_count + geomstrings_count + fragstrings_count)
1187 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1191 qglUseProgram(p->program);CHECKGLERROR
1192 // look up all the uniform variable names we care about, so we don't
1193 // have to look them up every time we set them
1198 GLint activeuniformindex = 0;
1199 GLint numactiveuniforms = 0;
1200 char uniformname[128];
1201 GLsizei uniformnamelength = 0;
1202 GLint uniformsize = 0;
1203 GLenum uniformtype = 0;
1204 memset(uniformname, 0, sizeof(uniformname));
1205 qglGetProgramiv(p->program, GL_ACTIVE_UNIFORMS, &numactiveuniforms);
1206 Con_Printf("Shader has %i uniforms\n", numactiveuniforms);
1207 for (activeuniformindex = 0;activeuniformindex < numactiveuniforms;activeuniformindex++)
1209 qglGetActiveUniform(p->program, activeuniformindex, sizeof(uniformname) - 1, &uniformnamelength, &uniformsize, &uniformtype, uniformname);
1210 Con_Printf("Uniform %i name \"%s\" size %i type %i\n", (int)activeuniformindex, uniformname, (int)uniformsize, (int)uniformtype);
1215 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1216 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1217 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1218 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1219 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1220 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1221 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1222 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1223 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1224 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1225 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1226 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1227 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1228 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1229 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1230 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1231 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1232 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1233 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1234 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1235 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1236 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1237 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1238 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1239 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1240 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1241 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1242 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1243 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1244 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1245 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1246 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1247 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1248 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1249 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1250 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1251 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1252 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1253 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1254 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1255 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1256 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1257 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1258 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1259 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1260 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1261 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1262 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1263 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1264 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1265 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1266 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1267 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1268 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1269 p->loc_OffsetMapping_LodDistance = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1270 p->loc_OffsetMapping_Bias = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1271 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1272 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1273 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1274 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1275 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1276 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1277 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1278 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1279 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1280 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1281 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1282 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1283 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1284 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1285 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1286 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1287 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1288 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1289 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1290 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1291 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1292 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1293 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1294 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1295 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1296 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1297 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1298 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1299 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1300 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1301 // initialize the samplers to refer to the texture units we use
1302 p->tex_Texture_First = -1;
1303 p->tex_Texture_Second = -1;
1304 p->tex_Texture_GammaRamps = -1;
1305 p->tex_Texture_Normal = -1;
1306 p->tex_Texture_Color = -1;
1307 p->tex_Texture_Gloss = -1;
1308 p->tex_Texture_Glow = -1;
1309 p->tex_Texture_SecondaryNormal = -1;
1310 p->tex_Texture_SecondaryColor = -1;
1311 p->tex_Texture_SecondaryGloss = -1;
1312 p->tex_Texture_SecondaryGlow = -1;
1313 p->tex_Texture_Pants = -1;
1314 p->tex_Texture_Shirt = -1;
1315 p->tex_Texture_FogHeightTexture = -1;
1316 p->tex_Texture_FogMask = -1;
1317 p->tex_Texture_Lightmap = -1;
1318 p->tex_Texture_Deluxemap = -1;
1319 p->tex_Texture_Attenuation = -1;
1320 p->tex_Texture_Cube = -1;
1321 p->tex_Texture_Refraction = -1;
1322 p->tex_Texture_Reflection = -1;
1323 p->tex_Texture_ShadowMap2D = -1;
1324 p->tex_Texture_CubeProjection = -1;
1325 p->tex_Texture_ScreenNormalMap = -1;
1326 p->tex_Texture_ScreenDiffuse = -1;
1327 p->tex_Texture_ScreenSpecular = -1;
1328 p->tex_Texture_ReflectMask = -1;
1329 p->tex_Texture_ReflectCube = -1;
1330 p->tex_Texture_BounceGrid = -1;
1331 // bind the texture samplers in use
1333 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1334 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1335 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1336 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1337 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1338 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1339 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1340 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1341 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1342 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1343 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1344 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1345 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1346 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1347 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1348 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1349 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1350 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1351 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1352 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1353 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1354 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1355 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1356 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1357 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1358 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1359 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1360 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1361 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1362 // get the uniform block indices so we can bind them
1363 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1364 if (vid.support.arb_uniform_buffer_object)
1365 p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1368 p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1369 // clear the uniform block bindings
1370 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1371 // bind the uniform blocks in use
1373 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1374 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1376 // we're done compiling and setting up the shader, at least until it is used
1378 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1381 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1385 Mem_Free(sourcestring);
1388 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1390 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1391 if (r_glsl_permutation != perm)
1393 r_glsl_permutation = perm;
1394 if (!r_glsl_permutation->program)
1396 if (!r_glsl_permutation->compiled)
1398 Con_DPrintf("Compiling shader mode %u permutation %u\n", mode, permutation);
1399 R_GLSL_CompilePermutation(perm, mode, permutation);
1401 if (!r_glsl_permutation->program)
1403 // remove features until we find a valid permutation
1405 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1407 // reduce i more quickly whenever it would not remove any bits
1408 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1409 if (!(permutation & j))
1412 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1413 if (!r_glsl_permutation->compiled)
1414 R_GLSL_CompilePermutation(perm, mode, permutation);
1415 if (r_glsl_permutation->program)
1418 if (i >= SHADERPERMUTATION_COUNT)
1420 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1421 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1422 qglUseProgram(0);CHECKGLERROR
1423 return; // no bit left to clear, entire mode is broken
1428 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1430 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1431 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1432 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1440 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1441 extern D3DCAPS9 vid_d3d9caps;
1444 struct r_hlsl_permutation_s;
1445 typedef struct r_hlsl_permutation_s
1447 /// hash lookup data
1448 struct r_hlsl_permutation_s *hashnext;
1450 unsigned int permutation;
1452 /// indicates if we have tried compiling this permutation already
1454 /// NULL if compilation failed
1455 IDirect3DVertexShader9 *vertexshader;
1456 IDirect3DPixelShader9 *pixelshader;
1458 r_hlsl_permutation_t;
1460 typedef enum D3DVSREGISTER_e
1462 D3DVSREGISTER_TexMatrix = 0, // float4x4
1463 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1464 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1465 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1466 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1467 D3DVSREGISTER_ModelToLight = 20, // float4x4
1468 D3DVSREGISTER_EyePosition = 24,
1469 D3DVSREGISTER_FogPlane = 25,
1470 D3DVSREGISTER_LightDir = 26,
1471 D3DVSREGISTER_LightPosition = 27,
1475 typedef enum D3DPSREGISTER_e
1477 D3DPSREGISTER_Alpha = 0,
1478 D3DPSREGISTER_BloomBlur_Parameters = 1,
1479 D3DPSREGISTER_ClientTime = 2,
1480 D3DPSREGISTER_Color_Ambient = 3,
1481 D3DPSREGISTER_Color_Diffuse = 4,
1482 D3DPSREGISTER_Color_Specular = 5,
1483 D3DPSREGISTER_Color_Glow = 6,
1484 D3DPSREGISTER_Color_Pants = 7,
1485 D3DPSREGISTER_Color_Shirt = 8,
1486 D3DPSREGISTER_DeferredColor_Ambient = 9,
1487 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1488 D3DPSREGISTER_DeferredColor_Specular = 11,
1489 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1490 D3DPSREGISTER_DeferredMod_Specular = 13,
1491 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1492 D3DPSREGISTER_EyePosition = 15, // unused
1493 D3DPSREGISTER_FogColor = 16,
1494 D3DPSREGISTER_FogHeightFade = 17,
1495 D3DPSREGISTER_FogPlane = 18,
1496 D3DPSREGISTER_FogPlaneViewDist = 19,
1497 D3DPSREGISTER_FogRangeRecip = 20,
1498 D3DPSREGISTER_LightColor = 21,
1499 D3DPSREGISTER_LightDir = 22, // unused
1500 D3DPSREGISTER_LightPosition = 23,
1501 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1502 D3DPSREGISTER_PixelSize = 25,
1503 D3DPSREGISTER_ReflectColor = 26,
1504 D3DPSREGISTER_ReflectFactor = 27,
1505 D3DPSREGISTER_ReflectOffset = 28,
1506 D3DPSREGISTER_RefractColor = 29,
1507 D3DPSREGISTER_Saturation = 30,
1508 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1509 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1510 D3DPSREGISTER_ScreenToDepth = 33,
1511 D3DPSREGISTER_ShadowMap_Parameters = 34,
1512 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1513 D3DPSREGISTER_SpecularPower = 36,
1514 D3DPSREGISTER_UserVec1 = 37,
1515 D3DPSREGISTER_UserVec2 = 38,
1516 D3DPSREGISTER_UserVec3 = 39,
1517 D3DPSREGISTER_UserVec4 = 40,
1518 D3DPSREGISTER_ViewTintColor = 41,
1519 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1520 D3DPSREGISTER_BloomColorSubtract = 43,
1521 D3DPSREGISTER_ViewToLight = 44, // float4x4
1522 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1523 D3DPSREGISTER_NormalmapScrollBlend = 52,
1524 D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1525 D3DPSREGISTER_OffsetMapping_Bias = 54,
1530 /// information about each possible shader permutation
1531 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1532 /// currently selected permutation
1533 r_hlsl_permutation_t *r_hlsl_permutation;
1534 /// storage for permutations linked in the hash table
1535 memexpandablearray_t r_hlsl_permutationarray;
1537 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1539 //unsigned int hashdepth = 0;
1540 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1541 r_hlsl_permutation_t *p;
1542 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1544 if (p->mode == mode && p->permutation == permutation)
1546 //if (hashdepth > 10)
1547 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1552 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1554 p->permutation = permutation;
1555 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1556 r_hlsl_permutationhash[mode][hashindex] = p;
1557 //if (hashdepth > 10)
1558 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1563 //#include <d3dx9shader.h>
1564 //#include <d3dx9mesh.h>
1566 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1568 DWORD *vsbin = NULL;
1569 DWORD *psbin = NULL;
1570 fs_offset_t vsbinsize;
1571 fs_offset_t psbinsize;
1572 // IDirect3DVertexShader9 *vs = NULL;
1573 // IDirect3DPixelShader9 *ps = NULL;
1574 ID3DXBuffer *vslog = NULL;
1575 ID3DXBuffer *vsbuffer = NULL;
1576 ID3DXConstantTable *vsconstanttable = NULL;
1577 ID3DXBuffer *pslog = NULL;
1578 ID3DXBuffer *psbuffer = NULL;
1579 ID3DXConstantTable *psconstanttable = NULL;
1582 char temp[MAX_INPUTLINE];
1583 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1585 qboolean debugshader = gl_paranoid.integer != 0;
1586 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1587 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1590 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1591 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1593 if ((!vsbin && vertstring) || (!psbin && fragstring))
1595 const char* dllnames_d3dx9 [] =
1619 dllhandle_t d3dx9_dll = NULL;
1620 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1621 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1622 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1623 dllfunction_t d3dx9_dllfuncs[] =
1625 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1626 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1627 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1630 // 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...
1631 #ifndef ID3DXBuffer_GetBufferPointer
1632 #if !defined(__cplusplus) || defined(CINTERFACE)
1633 #define ID3DXBuffer_GetBufferPointer(p) (p)->lpVtbl->GetBufferPointer(p)
1634 #define ID3DXBuffer_GetBufferSize(p) (p)->lpVtbl->GetBufferSize(p)
1635 #define ID3DXBuffer_Release(p) (p)->lpVtbl->Release(p)
1637 #define ID3DXBuffer_GetBufferPointer(p) (p)->GetBufferPointer()
1638 #define ID3DXBuffer_GetBufferSize(p) (p)->GetBufferSize()
1639 #define ID3DXBuffer_Release(p) (p)->Release()
1642 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1644 DWORD shaderflags = 0;
1646 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1647 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1648 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1649 if (vertstring && vertstring[0])
1653 FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1654 vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1657 vsresult = qD3DXCompileShader(vertstring, (unsigned int)strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1660 vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1661 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1662 memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1663 ID3DXBuffer_Release(vsbuffer);
1667 strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1668 Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1669 ID3DXBuffer_Release(vslog);
1672 if (fragstring && fragstring[0])
1676 FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1677 psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1680 psresult = qD3DXCompileShader(fragstring, (unsigned int)strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1683 psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1684 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1685 memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1686 ID3DXBuffer_Release(psbuffer);
1690 strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1691 Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1692 ID3DXBuffer_Release(pslog);
1695 Sys_UnloadLibrary(&d3dx9_dll);
1698 Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1702 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1703 if (FAILED(vsresult))
1704 Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1705 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1706 if (FAILED(psresult))
1707 Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1709 // free the shader data
1710 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1711 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1714 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1717 shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_HLSL][mode];
1718 int vertstring_length = 0;
1719 int geomstring_length = 0;
1720 int fragstring_length = 0;
1723 char *vertstring, *geomstring, *fragstring;
1724 char permutationname[256];
1725 char cachename[256];
1726 int vertstrings_count = 0;
1727 int geomstrings_count = 0;
1728 int fragstrings_count = 0;
1729 const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1730 const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1731 const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1736 p->vertexshader = NULL;
1737 p->pixelshader = NULL;
1739 permutationname[0] = 0;
1741 sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1743 strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1744 strlcat(cachename, "hlsl/", sizeof(cachename));
1746 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1747 vertstrings_count = 0;
1748 geomstrings_count = 0;
1749 fragstrings_count = 0;
1750 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1751 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1752 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1754 // the first pretext is which type of shader to compile as
1755 // (later these will all be bound together as a program object)
1756 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1757 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1758 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1760 // the second pretext is the mode (for example a light source)
1761 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1762 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1763 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1764 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1765 strlcat(cachename, modeinfo->name, sizeof(cachename));
1767 // now add all the permutation pretexts
1768 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1770 if (permutation & (1<<i))
1772 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1773 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1774 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1775 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1776 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1780 // keep line numbers correct
1781 vertstrings_list[vertstrings_count++] = "\n";
1782 geomstrings_list[geomstrings_count++] = "\n";
1783 fragstrings_list[fragstrings_count++] = "\n";
1788 R_CompileShader_AddStaticParms(mode, permutation);
1789 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1790 vertstrings_count += shaderstaticparms_count;
1791 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1792 geomstrings_count += shaderstaticparms_count;
1793 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1794 fragstrings_count += shaderstaticparms_count;
1796 // replace spaces in the cachename with _ characters
1797 for (i = 0;cachename[i];i++)
1798 if (cachename[i] == ' ')
1801 // now append the shader text itself
1802 vertstrings_list[vertstrings_count++] = sourcestring;
1803 geomstrings_list[geomstrings_count++] = sourcestring;
1804 fragstrings_list[fragstrings_count++] = sourcestring;
1806 vertstring_length = 0;
1807 for (i = 0;i < vertstrings_count;i++)
1808 vertstring_length += (int)strlen(vertstrings_list[i]);
1809 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1810 for (i = 0;i < vertstrings_count;t += (int)strlen(vertstrings_list[i]), i++)
1811 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1813 geomstring_length = 0;
1814 for (i = 0;i < geomstrings_count;i++)
1815 geomstring_length += (int)strlen(geomstrings_list[i]);
1816 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1817 for (i = 0;i < geomstrings_count;t += (int)strlen(geomstrings_list[i]), i++)
1818 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1820 fragstring_length = 0;
1821 for (i = 0;i < fragstrings_count;i++)
1822 fragstring_length += (int)strlen(fragstrings_list[i]);
1823 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1824 for (i = 0;i < fragstrings_count;t += (int)strlen(fragstrings_list[i]), i++)
1825 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1827 // try to load the cached shader, or generate one
1828 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1830 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1831 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1833 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1837 Mem_Free(vertstring);
1839 Mem_Free(geomstring);
1841 Mem_Free(fragstring);
1843 Mem_Free(sourcestring);
1846 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1847 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1848 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);}
1849 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);}
1850 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);}
1851 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);}
1853 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1854 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1855 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);}
1856 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);}
1857 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);}
1858 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);}
1860 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1862 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1863 if (r_hlsl_permutation != perm)
1865 r_hlsl_permutation = perm;
1866 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1868 if (!r_hlsl_permutation->compiled)
1869 R_HLSL_CompilePermutation(perm, mode, permutation);
1870 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1872 // remove features until we find a valid permutation
1874 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1876 // reduce i more quickly whenever it would not remove any bits
1877 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1878 if (!(permutation & j))
1881 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1882 if (!r_hlsl_permutation->compiled)
1883 R_HLSL_CompilePermutation(perm, mode, permutation);
1884 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1887 if (i >= SHADERPERMUTATION_COUNT)
1889 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1890 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1891 return; // no bit left to clear, entire mode is broken
1895 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1896 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1898 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1899 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1900 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1904 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1906 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1907 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1908 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1909 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1912 void R_GLSL_Restart_f(void)
1914 unsigned int i, limit;
1915 switch(vid.renderpath)
1917 case RENDERPATH_D3D9:
1920 r_hlsl_permutation_t *p;
1921 r_hlsl_permutation = NULL;
1922 limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1923 for (i = 0;i < limit;i++)
1925 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1927 if (p->vertexshader)
1928 IDirect3DVertexShader9_Release(p->vertexshader);
1930 IDirect3DPixelShader9_Release(p->pixelshader);
1931 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1934 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1938 case RENDERPATH_D3D10:
1939 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1941 case RENDERPATH_D3D11:
1942 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1944 case RENDERPATH_GL20:
1945 case RENDERPATH_GLES2:
1947 r_glsl_permutation_t *p;
1948 r_glsl_permutation = NULL;
1949 limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1950 for (i = 0;i < limit;i++)
1952 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1954 GL_Backend_FreeProgram(p->program);
1955 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1958 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1961 case RENDERPATH_GL11:
1962 case RENDERPATH_GL13:
1963 case RENDERPATH_GLES1:
1965 case RENDERPATH_SOFT:
1970 static void R_GLSL_DumpShader_f(void)
1972 int i, language, mode, dupe;
1974 shadermodeinfo_t *modeinfo;
1977 for (language = 0;language < SHADERLANGUAGE_COUNT;language++)
1979 modeinfo = shadermodeinfo[language];
1980 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1982 // don't dump the same file multiple times (most or all shaders come from the same file)
1983 for (dupe = mode - 1;dupe >= 0;dupe--)
1984 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1988 text = modeinfo[mode].builtinstring;
1991 file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
1994 FS_Print(file, "/* The engine may define the following macros:\n");
1995 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1996 for (i = 0;i < SHADERMODE_COUNT;i++)
1997 FS_Print(file, modeinfo[i].pretext);
1998 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1999 FS_Print(file, shaderpermutationinfo[i].pretext);
2000 FS_Print(file, "*/\n");
2001 FS_Print(file, text);
2003 Con_Printf("%s written\n", modeinfo[mode].filename);
2006 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
2011 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
2013 unsigned int permutation = 0;
2014 if (r_trippy.integer && !notrippy)
2015 permutation |= SHADERPERMUTATION_TRIPPY;
2016 permutation |= SHADERPERMUTATION_VIEWTINT;
2018 permutation |= SHADERPERMUTATION_DIFFUSE;
2020 permutation |= SHADERPERMUTATION_SPECULAR;
2021 if (texturemode == GL_MODULATE)
2022 permutation |= SHADERPERMUTATION_COLORMAPPING;
2023 else if (texturemode == GL_ADD)
2024 permutation |= SHADERPERMUTATION_GLOW;
2025 else if (texturemode == GL_DECAL)
2026 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2027 if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
2028 permutation |= SHADERPERMUTATION_GAMMARAMPS;
2029 if (suppresstexalpha)
2030 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2032 texturemode = GL_MODULATE;
2033 if (vid.allowalphatocoverage)
2034 GL_AlphaToCoverage(false);
2035 switch (vid.renderpath)
2037 case RENDERPATH_D3D9:
2039 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
2040 R_Mesh_TexBind(GL20TU_FIRST , first );
2041 R_Mesh_TexBind(GL20TU_SECOND, second);
2042 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
2043 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2046 case RENDERPATH_D3D10:
2047 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2049 case RENDERPATH_D3D11:
2050 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2052 case RENDERPATH_GL20:
2053 case RENDERPATH_GLES2:
2054 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2055 if (r_glsl_permutation->tex_Texture_First >= 0)
2056 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2057 if (r_glsl_permutation->tex_Texture_Second >= 0)
2058 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2059 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2060 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2062 case RENDERPATH_GL13:
2063 case RENDERPATH_GLES1:
2064 R_Mesh_TexBind(0, first );
2065 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2066 R_Mesh_TexMatrix(0, NULL);
2067 R_Mesh_TexBind(1, second);
2070 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2071 R_Mesh_TexMatrix(1, NULL);
2074 case RENDERPATH_GL11:
2075 R_Mesh_TexBind(0, first );
2076 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2077 R_Mesh_TexMatrix(0, NULL);
2079 case RENDERPATH_SOFT:
2080 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2081 R_Mesh_TexBind(GL20TU_FIRST , first );
2082 R_Mesh_TexBind(GL20TU_SECOND, second);
2087 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2089 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2092 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2094 unsigned int permutation = 0;
2095 if (r_trippy.integer && !notrippy)
2096 permutation |= SHADERPERMUTATION_TRIPPY;
2098 permutation |= SHADERPERMUTATION_DEPTHRGB;
2100 permutation |= SHADERPERMUTATION_SKELETAL;
2102 if (vid.allowalphatocoverage)
2103 GL_AlphaToCoverage(false);
2104 switch (vid.renderpath)
2106 case RENDERPATH_D3D9:
2108 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2111 case RENDERPATH_D3D10:
2112 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2114 case RENDERPATH_D3D11:
2115 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2117 case RENDERPATH_GL20:
2118 case RENDERPATH_GLES2:
2119 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2120 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2121 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);
2124 case RENDERPATH_GL13:
2125 case RENDERPATH_GLES1:
2126 R_Mesh_TexBind(0, 0);
2127 R_Mesh_TexBind(1, 0);
2129 case RENDERPATH_GL11:
2130 R_Mesh_TexBind(0, 0);
2132 case RENDERPATH_SOFT:
2133 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2138 extern qboolean r_shadow_usingdeferredprepass;
2139 extern rtexture_t *r_shadow_attenuationgradienttexture;
2140 extern rtexture_t *r_shadow_attenuation2dtexture;
2141 extern rtexture_t *r_shadow_attenuation3dtexture;
2142 extern qboolean r_shadow_usingshadowmap2d;
2143 extern qboolean r_shadow_usingshadowmaportho;
2144 extern float r_shadow_modelshadowmap_texturescale[4];
2145 extern float r_shadow_modelshadowmap_parameters[4];
2146 extern float r_shadow_lightshadowmap_texturescale[4];
2147 extern float r_shadow_lightshadowmap_parameters[4];
2148 extern qboolean r_shadow_shadowmapvsdct;
2149 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2150 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2151 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2152 extern matrix4x4_t r_shadow_shadowmapmatrix;
2153 extern int r_shadow_prepass_width;
2154 extern int r_shadow_prepass_height;
2155 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2156 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2157 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2158 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2160 #define BLENDFUNC_ALLOWS_COLORMOD 1
2161 #define BLENDFUNC_ALLOWS_FOG 2
2162 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2163 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2164 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2165 static int R_BlendFuncFlags(int src, int dst)
2169 // a blendfunc allows colormod if:
2170 // a) it can never keep the destination pixel invariant, or
2171 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2172 // this is to prevent unintended side effects from colormod
2174 // a blendfunc allows fog if:
2175 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2176 // this is to prevent unintended side effects from fog
2178 // these checks are the output of fogeval.pl
2180 r |= BLENDFUNC_ALLOWS_COLORMOD;
2181 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2182 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2183 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2184 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2185 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2186 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2187 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2188 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2189 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2190 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2191 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2192 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2193 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2194 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2195 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2196 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2197 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2198 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2199 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2200 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2201 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2206 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)
2208 // select a permutation of the lighting shader appropriate to this
2209 // combination of texture, entity, light source, and fogging, only use the
2210 // minimum features necessary to avoid wasting rendering time in the
2211 // fragment shader on features that are not being used
2212 unsigned int permutation = 0;
2213 unsigned int mode = 0;
2215 static float dummy_colormod[3] = {1, 1, 1};
2216 float *colormod = rsurface.colormod;
2218 matrix4x4_t tempmatrix;
2219 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2220 if (r_trippy.integer && !notrippy)
2221 permutation |= SHADERPERMUTATION_TRIPPY;
2222 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2223 permutation |= SHADERPERMUTATION_ALPHAKILL;
2224 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_OCCLUDE)
2225 permutation |= SHADERPERMUTATION_OCCLUDE;
2226 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2227 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2228 if (rsurfacepass == RSURFPASS_BACKGROUND)
2230 // distorted background
2231 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2233 mode = SHADERMODE_WATER;
2234 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2235 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2236 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2238 // this is the right thing to do for wateralpha
2239 GL_BlendFunc(GL_ONE, GL_ZERO);
2240 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2244 // this is the right thing to do for entity alpha
2245 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2246 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2249 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2251 mode = SHADERMODE_REFRACTION;
2252 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2253 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2254 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2255 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2259 mode = SHADERMODE_GENERIC;
2260 permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2261 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2262 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2264 if (vid.allowalphatocoverage)
2265 GL_AlphaToCoverage(false);
2267 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2269 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2271 switch(rsurface.texture->offsetmapping)
2273 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2274 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2275 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2276 case OFFSETMAPPING_OFF: break;
2279 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2280 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2281 // normalmap (deferred prepass), may use alpha test on diffuse
2282 mode = SHADERMODE_DEFERREDGEOMETRY;
2283 GL_BlendFunc(GL_ONE, GL_ZERO);
2284 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2285 if (vid.allowalphatocoverage)
2286 GL_AlphaToCoverage(false);
2288 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2290 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2292 switch(rsurface.texture->offsetmapping)
2294 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2295 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2296 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2297 case OFFSETMAPPING_OFF: break;
2300 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2301 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2302 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2303 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2305 mode = SHADERMODE_LIGHTSOURCE;
2306 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2307 permutation |= SHADERPERMUTATION_CUBEFILTER;
2308 if (diffusescale > 0)
2309 permutation |= SHADERPERMUTATION_DIFFUSE;
2310 if (specularscale > 0)
2311 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2312 if (r_refdef.fogenabled)
2313 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2314 if (rsurface.texture->colormapping)
2315 permutation |= SHADERPERMUTATION_COLORMAPPING;
2316 if (r_shadow_usingshadowmap2d)
2318 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2319 if(r_shadow_shadowmapvsdct)
2320 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2322 if (r_shadow_shadowmap2ddepthbuffer)
2323 permutation |= SHADERPERMUTATION_DEPTHRGB;
2325 if (rsurface.texture->reflectmasktexture)
2326 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2327 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2328 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2329 if (vid.allowalphatocoverage)
2330 GL_AlphaToCoverage(false);
2332 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2334 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2336 switch(rsurface.texture->offsetmapping)
2338 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2339 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2340 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2341 case OFFSETMAPPING_OFF: break;
2344 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2345 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2346 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2347 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2348 // unshaded geometry (fullbright or ambient model lighting)
2349 mode = SHADERMODE_FLATCOLOR;
2350 ambientscale = diffusescale = specularscale = 0;
2351 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2352 permutation |= SHADERPERMUTATION_GLOW;
2353 if (r_refdef.fogenabled)
2354 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2355 if (rsurface.texture->colormapping)
2356 permutation |= SHADERPERMUTATION_COLORMAPPING;
2357 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2359 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2360 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2362 if (r_shadow_shadowmap2ddepthbuffer)
2363 permutation |= SHADERPERMUTATION_DEPTHRGB;
2365 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2366 permutation |= SHADERPERMUTATION_REFLECTION;
2367 if (rsurface.texture->reflectmasktexture)
2368 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2369 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2370 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2371 // when using alphatocoverage, we don't need alphakill
2372 if (vid.allowalphatocoverage)
2374 if (r_transparent_alphatocoverage.integer)
2376 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2377 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2380 GL_AlphaToCoverage(false);
2383 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2385 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2387 switch(rsurface.texture->offsetmapping)
2389 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2390 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2391 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2392 case OFFSETMAPPING_OFF: break;
2395 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2396 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2397 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2398 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2399 // directional model lighting
2400 mode = SHADERMODE_LIGHTDIRECTION;
2401 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2402 permutation |= SHADERPERMUTATION_GLOW;
2403 permutation |= SHADERPERMUTATION_DIFFUSE;
2404 if (specularscale > 0)
2405 permutation |= SHADERPERMUTATION_SPECULAR;
2406 if (r_refdef.fogenabled)
2407 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2408 if (rsurface.texture->colormapping)
2409 permutation |= SHADERPERMUTATION_COLORMAPPING;
2410 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2412 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2413 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2415 if (r_shadow_shadowmap2ddepthbuffer)
2416 permutation |= SHADERPERMUTATION_DEPTHRGB;
2418 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2419 permutation |= SHADERPERMUTATION_REFLECTION;
2420 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2421 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2422 if (rsurface.texture->reflectmasktexture)
2423 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2424 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2426 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2427 if (r_shadow_bouncegrid_state.directional)
2428 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2430 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2431 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2432 // when using alphatocoverage, we don't need alphakill
2433 if (vid.allowalphatocoverage)
2435 if (r_transparent_alphatocoverage.integer)
2437 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2438 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2441 GL_AlphaToCoverage(false);
2444 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2446 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2448 switch(rsurface.texture->offsetmapping)
2450 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2451 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2452 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2453 case OFFSETMAPPING_OFF: break;
2456 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2457 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2458 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2459 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2460 // ambient model lighting
2461 mode = SHADERMODE_LIGHTDIRECTION;
2462 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2463 permutation |= SHADERPERMUTATION_GLOW;
2464 if (r_refdef.fogenabled)
2465 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2466 if (rsurface.texture->colormapping)
2467 permutation |= SHADERPERMUTATION_COLORMAPPING;
2468 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2470 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2471 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2473 if (r_shadow_shadowmap2ddepthbuffer)
2474 permutation |= SHADERPERMUTATION_DEPTHRGB;
2476 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2477 permutation |= SHADERPERMUTATION_REFLECTION;
2478 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2479 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2480 if (rsurface.texture->reflectmasktexture)
2481 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2482 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2484 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2485 if (r_shadow_bouncegrid_state.directional)
2486 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2488 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2489 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2490 // when using alphatocoverage, we don't need alphakill
2491 if (vid.allowalphatocoverage)
2493 if (r_transparent_alphatocoverage.integer)
2495 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2496 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2499 GL_AlphaToCoverage(false);
2504 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2506 switch(rsurface.texture->offsetmapping)
2508 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2509 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2510 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2511 case OFFSETMAPPING_OFF: break;
2514 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2515 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2516 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2517 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2519 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2520 permutation |= SHADERPERMUTATION_GLOW;
2521 if (r_refdef.fogenabled)
2522 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2523 if (rsurface.texture->colormapping)
2524 permutation |= SHADERPERMUTATION_COLORMAPPING;
2525 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2527 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2528 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2530 if (r_shadow_shadowmap2ddepthbuffer)
2531 permutation |= SHADERPERMUTATION_DEPTHRGB;
2533 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2534 permutation |= SHADERPERMUTATION_REFLECTION;
2535 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2536 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2537 if (rsurface.texture->reflectmasktexture)
2538 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2539 if (FAKELIGHT_ENABLED)
2541 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2542 mode = SHADERMODE_FAKELIGHT;
2543 permutation |= SHADERPERMUTATION_DIFFUSE;
2544 if (specularscale > 0)
2545 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2547 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2549 // deluxemapping (light direction texture)
2550 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2551 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2553 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2554 permutation |= SHADERPERMUTATION_DIFFUSE;
2555 if (specularscale > 0)
2556 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2558 else if (r_glsl_deluxemapping.integer >= 2)
2560 // fake deluxemapping (uniform light direction in tangentspace)
2561 if (rsurface.uselightmaptexture)
2562 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2564 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2565 permutation |= SHADERPERMUTATION_DIFFUSE;
2566 if (specularscale > 0)
2567 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2569 else if (rsurface.uselightmaptexture)
2571 // ordinary lightmapping (q1bsp, q3bsp)
2572 mode = SHADERMODE_LIGHTMAP;
2576 // ordinary vertex coloring (q3bsp)
2577 mode = SHADERMODE_VERTEXCOLOR;
2579 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2581 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2582 if (r_shadow_bouncegrid_state.directional)
2583 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2585 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2586 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2587 // when using alphatocoverage, we don't need alphakill
2588 if (vid.allowalphatocoverage)
2590 if (r_transparent_alphatocoverage.integer)
2592 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2593 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2596 GL_AlphaToCoverage(false);
2599 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2600 colormod = dummy_colormod;
2601 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2602 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2603 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2604 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2605 switch(vid.renderpath)
2607 case RENDERPATH_D3D9:
2609 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);
2610 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2611 R_SetupShader_SetPermutationHLSL(mode, permutation);
2612 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2613 if (mode == SHADERMODE_LIGHTSOURCE)
2615 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2616 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2620 if (mode == SHADERMODE_LIGHTDIRECTION)
2622 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2625 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2626 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2627 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2628 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2629 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2631 if (mode == SHADERMODE_LIGHTSOURCE)
2633 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2634 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2635 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2636 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2637 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2639 // additive passes are only darkened by fog, not tinted
2640 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2641 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2645 if (mode == SHADERMODE_FLATCOLOR)
2647 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2649 else if (mode == SHADERMODE_LIGHTDIRECTION)
2651 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]);
2652 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2653 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);
2654 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2655 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2656 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2657 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2661 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2662 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2663 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);
2664 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2665 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2667 // additive passes are only darkened by fog, not tinted
2668 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2669 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2671 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2672 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);
2673 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2674 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2675 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2676 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2677 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2678 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2679 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2680 if (mode == SHADERMODE_WATER)
2681 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2683 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2685 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]);
2686 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]);
2690 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
2691 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
2693 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2694 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));
2695 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2696 if (rsurface.texture->pantstexture)
2697 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2699 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2700 if (rsurface.texture->shirttexture)
2701 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2703 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2704 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2705 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2706 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2707 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2708 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2709 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2710 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2711 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2712 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2714 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2715 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2716 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2717 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2719 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2720 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2721 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2722 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2723 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2724 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2725 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2726 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2727 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2728 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2729 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2730 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2731 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2732 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2733 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2734 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2735 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2736 if (rsurfacepass == RSURFPASS_BACKGROUND)
2738 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2739 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2740 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2744 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2746 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2747 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2748 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2749 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2751 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2752 if (rsurface.rtlight)
2754 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2755 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2760 case RENDERPATH_D3D10:
2761 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2763 case RENDERPATH_D3D11:
2764 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2766 case RENDERPATH_GL20:
2767 case RENDERPATH_GLES2:
2768 if (!vid.useinterleavedarrays)
2770 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);
2771 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2772 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2773 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2774 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2775 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2776 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2777 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2778 R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2779 R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2780 R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2784 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);
2785 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2787 // this has to be after RSurf_PrepareVerticesForBatch
2788 if (rsurface.batchskeletaltransform3x4buffer)
2789 permutation |= SHADERPERMUTATION_SKELETAL;
2790 R_SetupShader_SetPermutationGLSL(mode, permutation);
2791 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2792 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);
2794 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2795 if (mode == SHADERMODE_LIGHTSOURCE)
2797 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2798 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2799 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2800 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2801 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2802 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);
2804 // additive passes are only darkened by fog, not tinted
2805 if (r_glsl_permutation->loc_FogColor >= 0)
2806 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2807 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);
2811 if (mode == SHADERMODE_FLATCOLOR)
2813 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2815 else if (mode == SHADERMODE_LIGHTDIRECTION)
2817 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]);
2818 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]);
2819 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);
2820 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2821 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2822 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]);
2823 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]);
2827 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]);
2828 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]);
2829 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);
2830 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2831 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2833 // additive passes are only darkened by fog, not tinted
2834 if (r_glsl_permutation->loc_FogColor >= 0)
2836 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2837 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2839 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2841 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);
2842 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]);
2843 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]);
2844 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]);
2845 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]);
2846 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2847 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2848 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);
2849 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]);
2851 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2852 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2853 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2854 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2856 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]);
2857 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]);
2861 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
2862 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
2865 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2866 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));
2867 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2868 if (r_glsl_permutation->loc_Color_Pants >= 0)
2870 if (rsurface.texture->pantstexture)
2871 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2873 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2875 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2877 if (rsurface.texture->shirttexture)
2878 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2880 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2882 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]);
2883 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2884 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2885 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2886 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2887 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2888 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2889 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2890 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2892 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);
2893 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2894 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]);
2895 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2896 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);}
2897 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegrid_state.intensity*r_refdef.view.colorscale);
2899 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2900 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2901 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2902 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2903 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2904 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2905 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2906 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2907 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2908 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2909 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2910 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2911 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2912 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2913 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);
2914 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2915 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2916 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2917 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2918 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2919 if (rsurfacepass == RSURFPASS_BACKGROUND)
2921 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);
2922 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);
2923 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);
2927 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);
2929 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2930 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2931 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2932 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2934 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture );
2935 if (rsurface.rtlight)
2937 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2938 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2941 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegrid_state.texture);
2944 case RENDERPATH_GL11:
2945 case RENDERPATH_GL13:
2946 case RENDERPATH_GLES1:
2948 case RENDERPATH_SOFT:
2949 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);
2950 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2951 R_SetupShader_SetPermutationSoft(mode, permutation);
2952 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2953 if (mode == SHADERMODE_LIGHTSOURCE)
2955 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2956 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2957 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2958 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2959 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2960 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2962 // additive passes are only darkened by fog, not tinted
2963 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2964 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2968 if (mode == SHADERMODE_FLATCOLOR)
2970 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2972 else if (mode == SHADERMODE_LIGHTDIRECTION)
2974 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]);
2975 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2976 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);
2977 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2978 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2979 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]);
2980 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2984 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2985 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2986 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);
2987 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2988 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2990 // additive passes are only darkened by fog, not tinted
2991 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2992 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2994 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2995 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);
2996 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]);
2997 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]);
2998 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]);
2999 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]);
3000 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
3001 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
3002 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3003 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
3005 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
3006 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
3007 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
3008 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
3010 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]);
3011 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]);
3015 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3016 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3019 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
3020 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));
3021 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
3022 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
3024 if (rsurface.texture->pantstexture)
3025 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
3027 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
3029 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
3031 if (rsurface.texture->shirttexture)
3032 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
3034 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
3036 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
3037 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
3038 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
3039 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
3040 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
3041 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
3042 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3043 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3044 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
3046 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
3047 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
3048 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3049 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3051 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
3052 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
3053 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
3054 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
3055 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
3056 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
3057 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
3058 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
3059 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
3060 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
3061 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
3062 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
3063 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
3064 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
3065 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
3066 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
3067 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3068 if (rsurfacepass == RSURFPASS_BACKGROUND)
3070 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
3071 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
3072 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3076 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3078 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3079 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
3080 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
3081 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
3083 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
3084 if (rsurface.rtlight)
3086 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3087 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3094 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3096 // select a permutation of the lighting shader appropriate to this
3097 // combination of texture, entity, light source, and fogging, only use the
3098 // minimum features necessary to avoid wasting rendering time in the
3099 // fragment shader on features that are not being used
3100 unsigned int permutation = 0;
3101 unsigned int mode = 0;
3102 const float *lightcolorbase = rtlight->currentcolor;
3103 float ambientscale = rtlight->ambientscale;
3104 float diffusescale = rtlight->diffusescale;
3105 float specularscale = rtlight->specularscale;
3106 // this is the location of the light in view space
3107 vec3_t viewlightorigin;
3108 // this transforms from view space (camera) to light space (cubemap)
3109 matrix4x4_t viewtolight;
3110 matrix4x4_t lighttoview;
3111 float viewtolight16f[16];
3113 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3114 if (rtlight->currentcubemap != r_texture_whitecube)
3115 permutation |= SHADERPERMUTATION_CUBEFILTER;
3116 if (diffusescale > 0)
3117 permutation |= SHADERPERMUTATION_DIFFUSE;
3118 if (specularscale > 0 && r_shadow_gloss.integer > 0)
3119 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3120 if (r_shadow_usingshadowmap2d)
3122 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3123 if (r_shadow_shadowmapvsdct)
3124 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3126 if (r_shadow_shadowmap2ddepthbuffer)
3127 permutation |= SHADERPERMUTATION_DEPTHRGB;
3129 if (vid.allowalphatocoverage)
3130 GL_AlphaToCoverage(false);
3131 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3132 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3133 Matrix4x4_Invert_Full(&viewtolight, &lighttoview);
3134 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3135 switch(vid.renderpath)
3137 case RENDERPATH_D3D9:
3139 R_SetupShader_SetPermutationHLSL(mode, permutation);
3140 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3141 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3142 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3143 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3144 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3145 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3146 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3147 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);
3148 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3149 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3151 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3152 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3153 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3154 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2ddepthtexture );
3155 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3158 case RENDERPATH_D3D10:
3159 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3161 case RENDERPATH_D3D11:
3162 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3164 case RENDERPATH_GL20:
3165 case RENDERPATH_GLES2:
3166 R_SetupShader_SetPermutationGLSL(mode, permutation);
3167 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3168 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
3169 if (r_glsl_permutation->loc_DeferredColor_Ambient >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3170 if (r_glsl_permutation->loc_DeferredColor_Diffuse >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3171 if (r_glsl_permutation->loc_DeferredColor_Specular >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3172 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform4f( r_glsl_permutation->loc_ShadowMap_TextureScale , r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3173 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f( r_glsl_permutation->loc_ShadowMap_Parameters , r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3174 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);
3175 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]);
3176 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
3178 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
3179 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
3180 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
3181 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2ddepthtexture );
3182 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
3184 case RENDERPATH_GL11:
3185 case RENDERPATH_GL13:
3186 case RENDERPATH_GLES1:
3188 case RENDERPATH_SOFT:
3189 R_SetupShader_SetPermutationGLSL(mode, permutation);
3190 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3191 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
3192 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3193 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3194 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3195 DPSOFTRAST_Uniform4f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3196 DPSOFTRAST_Uniform4f( DPSOFTRAST_UNIFORM_ShadowMap_Parameters , r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3197 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);
3198 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3199 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3201 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3202 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3203 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3204 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2ddepthtexture );
3205 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3210 #define SKINFRAME_HASH 1024
3214 unsigned int loadsequence; // incremented each level change
3215 memexpandablearray_t array;
3216 skinframe_t *hash[SKINFRAME_HASH];
3219 r_skinframe_t r_skinframe;
3221 void R_SkinFrame_PrepareForPurge(void)
3223 r_skinframe.loadsequence++;
3224 // wrap it without hitting zero
3225 if (r_skinframe.loadsequence >= 200)
3226 r_skinframe.loadsequence = 1;
3229 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3233 // mark the skinframe as used for the purging code
3234 skinframe->loadsequence = r_skinframe.loadsequence;
3237 void R_SkinFrame_Purge(void)
3241 for (i = 0;i < SKINFRAME_HASH;i++)
3243 for (s = r_skinframe.hash[i];s;s = s->next)
3245 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3247 if (s->merged == s->base)
3249 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3250 R_PurgeTexture(s->stain );s->stain = NULL;
3251 R_PurgeTexture(s->merged);s->merged = NULL;
3252 R_PurgeTexture(s->base );s->base = NULL;
3253 R_PurgeTexture(s->pants );s->pants = NULL;
3254 R_PurgeTexture(s->shirt );s->shirt = NULL;
3255 R_PurgeTexture(s->nmap );s->nmap = NULL;
3256 R_PurgeTexture(s->gloss );s->gloss = NULL;
3257 R_PurgeTexture(s->glow );s->glow = NULL;
3258 R_PurgeTexture(s->fog );s->fog = NULL;
3259 R_PurgeTexture(s->reflect);s->reflect = NULL;
3260 s->loadsequence = 0;
3266 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3268 char basename[MAX_QPATH];
3270 Image_StripImageExtension(name, basename, sizeof(basename));
3272 if( last == NULL ) {
3274 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3275 item = r_skinframe.hash[hashindex];
3280 // linearly search through the hash bucket
3281 for( ; item ; item = item->next ) {
3282 if( !strcmp( item->basename, basename ) ) {
3289 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3293 char basename[MAX_QPATH];
3295 Image_StripImageExtension(name, basename, sizeof(basename));
3297 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3298 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3299 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3303 rtexture_t *dyntexture;
3304 // check whether its a dynamic texture
3305 dyntexture = CL_GetDynTexture( basename );
3306 if (!add && !dyntexture)
3308 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3309 memset(item, 0, sizeof(*item));
3310 strlcpy(item->basename, basename, sizeof(item->basename));
3311 item->base = dyntexture; // either NULL or dyntexture handle
3312 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3313 item->comparewidth = comparewidth;
3314 item->compareheight = compareheight;
3315 item->comparecrc = comparecrc;
3316 item->next = r_skinframe.hash[hashindex];
3317 r_skinframe.hash[hashindex] = item;
3319 else if (textureflags & TEXF_FORCE_RELOAD)
3321 rtexture_t *dyntexture;
3322 // check whether its a dynamic texture
3323 dyntexture = CL_GetDynTexture( basename );
3324 if (!add && !dyntexture)
3326 if (item->merged == item->base)
3327 item->merged = NULL;
3328 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3329 R_PurgeTexture(item->stain );item->stain = NULL;
3330 R_PurgeTexture(item->merged);item->merged = NULL;
3331 R_PurgeTexture(item->base );item->base = NULL;
3332 R_PurgeTexture(item->pants );item->pants = NULL;
3333 R_PurgeTexture(item->shirt );item->shirt = NULL;
3334 R_PurgeTexture(item->nmap );item->nmap = NULL;
3335 R_PurgeTexture(item->gloss );item->gloss = NULL;
3336 R_PurgeTexture(item->glow );item->glow = NULL;
3337 R_PurgeTexture(item->fog );item->fog = NULL;
3338 R_PurgeTexture(item->reflect);item->reflect = NULL;
3339 item->loadsequence = 0;
3341 else if( item->base == NULL )
3343 rtexture_t *dyntexture;
3344 // check whether its a dynamic texture
3345 // 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]
3346 dyntexture = CL_GetDynTexture( basename );
3347 item->base = dyntexture; // either NULL or dyntexture handle
3350 R_SkinFrame_MarkUsed(item);
3354 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3356 unsigned long long avgcolor[5], wsum; \
3364 for(pix = 0; pix < cnt; ++pix) \
3367 for(comp = 0; comp < 3; ++comp) \
3369 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3372 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3374 for(comp = 0; comp < 3; ++comp) \
3375 avgcolor[comp] += getpixel * w; \
3378 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3379 avgcolor[4] += getpixel; \
3381 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3383 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3384 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3385 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3386 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3389 extern cvar_t gl_picmip;
3390 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3393 unsigned char *pixels;
3394 unsigned char *bumppixels;
3395 unsigned char *basepixels = NULL;
3396 int basepixels_width = 0;
3397 int basepixels_height = 0;
3398 skinframe_t *skinframe;
3399 rtexture_t *ddsbase = NULL;
3400 qboolean ddshasalpha = false;
3401 float ddsavgcolor[4];
3402 char basename[MAX_QPATH];
3403 int miplevel = R_PicmipForFlags(textureflags);
3404 int savemiplevel = miplevel;
3408 if (cls.state == ca_dedicated)
3411 // return an existing skinframe if already loaded
3412 // if loading of the first image fails, don't make a new skinframe as it
3413 // would cause all future lookups of this to be missing
3414 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3415 if (skinframe && skinframe->base)
3418 Image_StripImageExtension(name, basename, sizeof(basename));
3420 // check for DDS texture file first
3421 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3423 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3424 if (basepixels == NULL)
3428 // FIXME handle miplevel
3430 if (developer_loading.integer)
3431 Con_Printf("loading skin \"%s\"\n", name);
3433 // we've got some pixels to store, so really allocate this new texture now
3435 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3436 textureflags &= ~TEXF_FORCE_RELOAD;
3437 skinframe->stain = NULL;
3438 skinframe->merged = NULL;
3439 skinframe->base = NULL;
3440 skinframe->pants = NULL;
3441 skinframe->shirt = NULL;
3442 skinframe->nmap = NULL;
3443 skinframe->gloss = NULL;
3444 skinframe->glow = NULL;
3445 skinframe->fog = NULL;
3446 skinframe->reflect = NULL;
3447 skinframe->hasalpha = false;
3448 // we could store the q2animname here too
3452 skinframe->base = ddsbase;
3453 skinframe->hasalpha = ddshasalpha;
3454 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3455 if (r_loadfog && skinframe->hasalpha)
3456 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);
3457 //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 basepixels_width = image_width;
3462 basepixels_height = image_height;
3463 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);
3464 if (textureflags & TEXF_ALPHA)
3466 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3468 if (basepixels[j] < 255)
3470 skinframe->hasalpha = true;
3474 if (r_loadfog && skinframe->hasalpha)
3476 // has transparent pixels
3477 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3478 for (j = 0;j < image_width * image_height * 4;j += 4)
3483 pixels[j+3] = basepixels[j+3];
3485 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);
3489 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3491 //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]);
3492 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3493 R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3494 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3495 R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3501 mymiplevel = savemiplevel;
3502 if (r_loadnormalmap)
3503 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);
3504 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3506 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3507 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3508 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3509 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3512 // _norm is the name used by tenebrae and has been adopted as standard
3513 if (r_loadnormalmap && skinframe->nmap == NULL)
3515 mymiplevel = savemiplevel;
3516 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3518 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);
3522 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3524 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3525 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3526 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);
3528 Mem_Free(bumppixels);
3530 else if (r_shadow_bumpscale_basetexture.value > 0)
3532 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3533 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3534 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);
3538 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3539 R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3543 // _luma is supported only for tenebrae compatibility
3544 // _glow is the preferred name
3545 mymiplevel = savemiplevel;
3546 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))))
3548 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);
3550 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3551 R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3553 Mem_Free(pixels);pixels = NULL;
3556 mymiplevel = savemiplevel;
3557 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3559 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);
3561 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3562 R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3568 mymiplevel = savemiplevel;
3569 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3571 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);
3573 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3574 R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3580 mymiplevel = savemiplevel;
3581 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3583 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);
3585 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3586 R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3592 mymiplevel = savemiplevel;
3593 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3595 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);
3597 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3598 R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3605 Mem_Free(basepixels);
3610 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3611 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3614 skinframe_t *skinframe;
3617 if (cls.state == ca_dedicated)
3620 // if already loaded just return it, otherwise make a new skinframe
3621 skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3622 if (skinframe->base)
3624 textureflags &= ~TEXF_FORCE_RELOAD;
3626 skinframe->stain = NULL;
3627 skinframe->merged = NULL;
3628 skinframe->base = NULL;
3629 skinframe->pants = NULL;
3630 skinframe->shirt = NULL;
3631 skinframe->nmap = NULL;
3632 skinframe->gloss = NULL;
3633 skinframe->glow = NULL;
3634 skinframe->fog = NULL;
3635 skinframe->reflect = NULL;
3636 skinframe->hasalpha = false;
3638 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3642 if (developer_loading.integer)
3643 Con_Printf("loading 32bit skin \"%s\"\n", name);
3645 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3647 unsigned char *a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3648 unsigned char *b = a + width * height * 4;
3649 Image_HeightmapToNormalmap_BGRA(skindata, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3650 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);
3653 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3654 if (textureflags & TEXF_ALPHA)
3656 for (i = 3;i < width * height * 4;i += 4)
3658 if (skindata[i] < 255)
3660 skinframe->hasalpha = true;
3664 if (r_loadfog && skinframe->hasalpha)
3666 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3667 memcpy(fogpixels, skindata, width * height * 4);
3668 for (i = 0;i < width * height * 4;i += 4)
3669 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3670 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3671 Mem_Free(fogpixels);
3675 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3676 //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]);
3681 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3685 skinframe_t *skinframe;
3687 if (cls.state == ca_dedicated)
3690 // if already loaded just return it, otherwise make a new skinframe
3691 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3692 if (skinframe->base)
3694 //textureflags &= ~TEXF_FORCE_RELOAD;
3696 skinframe->stain = NULL;
3697 skinframe->merged = NULL;
3698 skinframe->base = NULL;
3699 skinframe->pants = NULL;
3700 skinframe->shirt = NULL;
3701 skinframe->nmap = NULL;
3702 skinframe->gloss = NULL;
3703 skinframe->glow = NULL;
3704 skinframe->fog = NULL;
3705 skinframe->reflect = NULL;
3706 skinframe->hasalpha = false;
3708 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3712 if (developer_loading.integer)
3713 Con_Printf("loading quake skin \"%s\"\n", name);
3715 // 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)
3716 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3717 memcpy(skinframe->qpixels, skindata, width*height);
3718 skinframe->qwidth = width;
3719 skinframe->qheight = height;
3722 for (i = 0;i < width * height;i++)
3723 featuresmask |= palette_featureflags[skindata[i]];
3725 skinframe->hasalpha = false;
3728 skinframe->hasalpha = true;
3729 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3730 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3731 skinframe->qgeneratemerged = true;
3732 skinframe->qgeneratebase = skinframe->qhascolormapping;
3733 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3735 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3736 //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]);
3741 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3745 unsigned char *skindata;
3748 if (!skinframe->qpixels)
3751 if (!skinframe->qhascolormapping)
3752 colormapped = false;
3756 if (!skinframe->qgeneratebase)
3761 if (!skinframe->qgeneratemerged)
3765 width = skinframe->qwidth;
3766 height = skinframe->qheight;
3767 skindata = skinframe->qpixels;
3769 if (skinframe->qgeneratenmap)
3771 unsigned char *a, *b;
3772 skinframe->qgeneratenmap = false;
3773 a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3774 b = a + width * height * 4;
3775 // use either a custom palette or the quake palette
3776 Image_Copy8bitBGRA(skindata, a, width * height, palette_bgra_complete);
3777 Image_HeightmapToNormalmap_BGRA(a, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3778 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);
3782 if (skinframe->qgenerateglow)
3784 skinframe->qgenerateglow = false;
3785 if (skinframe->hasalpha) // fence textures
3786 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
3788 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
3793 skinframe->qgeneratebase = false;
3794 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);
3795 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);
3796 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);
3800 skinframe->qgeneratemerged = false;
3801 if (skinframe->hasalpha) // fence textures
3802 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);
3804 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);
3807 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3809 Mem_Free(skinframe->qpixels);
3810 skinframe->qpixels = NULL;
3814 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)
3817 skinframe_t *skinframe;
3820 if (cls.state == ca_dedicated)
3823 // if already loaded just return it, otherwise make a new skinframe
3824 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3825 if (skinframe->base)
3827 textureflags &= ~TEXF_FORCE_RELOAD;
3829 skinframe->stain = NULL;
3830 skinframe->merged = NULL;
3831 skinframe->base = NULL;
3832 skinframe->pants = NULL;
3833 skinframe->shirt = NULL;
3834 skinframe->nmap = NULL;
3835 skinframe->gloss = NULL;
3836 skinframe->glow = NULL;
3837 skinframe->fog = NULL;
3838 skinframe->reflect = NULL;
3839 skinframe->hasalpha = false;
3841 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3845 if (developer_loading.integer)
3846 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3848 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3849 if (textureflags & TEXF_ALPHA)
3851 for (i = 0;i < width * height;i++)
3853 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3855 skinframe->hasalpha = true;
3859 if (r_loadfog && skinframe->hasalpha)
3860 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3863 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3864 //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]);
3869 skinframe_t *R_SkinFrame_LoadMissing(void)
3871 skinframe_t *skinframe;
3873 if (cls.state == ca_dedicated)
3876 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3877 skinframe->stain = NULL;
3878 skinframe->merged = NULL;
3879 skinframe->base = NULL;
3880 skinframe->pants = NULL;
3881 skinframe->shirt = NULL;
3882 skinframe->nmap = NULL;
3883 skinframe->gloss = NULL;
3884 skinframe->glow = NULL;
3885 skinframe->fog = NULL;
3886 skinframe->reflect = NULL;
3887 skinframe->hasalpha = false;
3889 skinframe->avgcolor[0] = rand() / RAND_MAX;
3890 skinframe->avgcolor[1] = rand() / RAND_MAX;
3891 skinframe->avgcolor[2] = rand() / RAND_MAX;
3892 skinframe->avgcolor[3] = 1;
3897 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3898 typedef struct suffixinfo_s
3901 qboolean flipx, flipy, flipdiagonal;
3904 static suffixinfo_t suffix[3][6] =
3907 {"px", false, false, false},
3908 {"nx", false, false, false},
3909 {"py", false, false, false},
3910 {"ny", false, false, false},
3911 {"pz", false, false, false},
3912 {"nz", false, false, false}
3915 {"posx", false, false, false},
3916 {"negx", false, false, false},
3917 {"posy", false, false, false},
3918 {"negy", false, false, false},
3919 {"posz", false, false, false},
3920 {"negz", false, false, false}
3923 {"rt", true, false, true},
3924 {"lf", false, true, true},
3925 {"ft", true, true, false},
3926 {"bk", false, false, false},
3927 {"up", true, false, true},
3928 {"dn", true, false, true}
3932 static int componentorder[4] = {0, 1, 2, 3};
3934 static rtexture_t *R_LoadCubemap(const char *basename)
3936 int i, j, cubemapsize;
3937 unsigned char *cubemappixels, *image_buffer;
3938 rtexture_t *cubemaptexture;
3940 // must start 0 so the first loadimagepixels has no requested width/height
3942 cubemappixels = NULL;
3943 cubemaptexture = NULL;
3944 // keep trying different suffix groups (posx, px, rt) until one loads
3945 for (j = 0;j < 3 && !cubemappixels;j++)
3947 // load the 6 images in the suffix group
3948 for (i = 0;i < 6;i++)
3950 // generate an image name based on the base and and suffix
3951 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3953 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3955 // an image loaded, make sure width and height are equal
3956 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3958 // if this is the first image to load successfully, allocate the cubemap memory
3959 if (!cubemappixels && image_width >= 1)
3961 cubemapsize = image_width;
3962 // note this clears to black, so unavailable sides are black
3963 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3965 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3967 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);
3970 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3972 Mem_Free(image_buffer);
3976 // if a cubemap loaded, upload it
3979 if (developer_loading.integer)
3980 Con_Printf("loading cubemap \"%s\"\n", basename);
3982 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);
3983 Mem_Free(cubemappixels);
3987 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3988 if (developer_loading.integer)
3990 Con_Printf("(tried tried images ");
3991 for (j = 0;j < 3;j++)
3992 for (i = 0;i < 6;i++)
3993 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3994 Con_Print(" and was unable to find any of them).\n");
3997 return cubemaptexture;
4000 rtexture_t *R_GetCubemap(const char *basename)
4003 for (i = 0;i < r_texture_numcubemaps;i++)
4004 if (r_texture_cubemaps[i] != NULL)
4005 if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
4006 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
4007 if (i >= MAX_CUBEMAPS || !r_main_mempool)
4008 return r_texture_whitecube;
4009 r_texture_numcubemaps++;
4010 r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
4011 strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
4012 r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
4013 return r_texture_cubemaps[i]->texture;
4016 static void R_Main_FreeViewCache(void)
4018 if (r_refdef.viewcache.entityvisible)
4019 Mem_Free(r_refdef.viewcache.entityvisible);
4020 if (r_refdef.viewcache.world_pvsbits)
4021 Mem_Free(r_refdef.viewcache.world_pvsbits);
4022 if (r_refdef.viewcache.world_leafvisible)
4023 Mem_Free(r_refdef.viewcache.world_leafvisible);
4024 if (r_refdef.viewcache.world_surfacevisible)
4025 Mem_Free(r_refdef.viewcache.world_surfacevisible);
4026 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
4029 static void R_Main_ResizeViewCache(void)
4031 int numentities = r_refdef.scene.numentities;
4032 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
4033 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
4034 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
4035 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
4036 if (r_refdef.viewcache.maxentities < numentities)
4038 r_refdef.viewcache.maxentities = numentities;
4039 if (r_refdef.viewcache.entityvisible)
4040 Mem_Free(r_refdef.viewcache.entityvisible);
4041 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
4043 if (r_refdef.viewcache.world_numclusters != numclusters)
4045 r_refdef.viewcache.world_numclusters = numclusters;
4046 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
4047 if (r_refdef.viewcache.world_pvsbits)
4048 Mem_Free(r_refdef.viewcache.world_pvsbits);
4049 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
4051 if (r_refdef.viewcache.world_numleafs != numleafs)
4053 r_refdef.viewcache.world_numleafs = numleafs;
4054 if (r_refdef.viewcache.world_leafvisible)
4055 Mem_Free(r_refdef.viewcache.world_leafvisible);
4056 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
4058 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
4060 r_refdef.viewcache.world_numsurfaces = numsurfaces;
4061 if (r_refdef.viewcache.world_surfacevisible)
4062 Mem_Free(r_refdef.viewcache.world_surfacevisible);
4063 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
4067 extern rtexture_t *loadingscreentexture;
4068 static void gl_main_start(void)
4070 loadingscreentexture = NULL;
4071 r_texture_blanknormalmap = NULL;
4072 r_texture_white = NULL;
4073 r_texture_grey128 = NULL;
4074 r_texture_black = NULL;
4075 r_texture_whitecube = NULL;
4076 r_texture_normalizationcube = NULL;
4077 r_texture_fogattenuation = NULL;
4078 r_texture_fogheighttexture = NULL;
4079 r_texture_gammaramps = NULL;
4080 r_texture_numcubemaps = 0;
4081 r_uniformbufferalignment = 32;
4083 r_loaddds = r_texture_dds_load.integer != 0;
4084 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
4086 switch(vid.renderpath)
4088 case RENDERPATH_GL20:
4089 case RENDERPATH_D3D9:
4090 case RENDERPATH_D3D10:
4091 case RENDERPATH_D3D11:
4092 case RENDERPATH_SOFT:
4093 case RENDERPATH_GLES2:
4094 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4095 Cvar_SetValueQuick(&gl_combine, 1);
4096 Cvar_SetValueQuick(&r_glsl, 1);
4097 r_loadnormalmap = true;
4100 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
4101 if (vid.support.arb_uniform_buffer_object)
4102 qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4105 case RENDERPATH_GL13:
4106 case RENDERPATH_GLES1:
4107 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4108 Cvar_SetValueQuick(&gl_combine, 1);
4109 Cvar_SetValueQuick(&r_glsl, 0);
4110 r_loadnormalmap = false;
4111 r_loadgloss = false;
4114 case RENDERPATH_GL11:
4115 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4116 Cvar_SetValueQuick(&gl_combine, 0);
4117 Cvar_SetValueQuick(&r_glsl, 0);
4118 r_loadnormalmap = false;
4119 r_loadgloss = false;
4125 R_FrameData_Reset();
4126 R_BufferData_Reset();
4130 memset(r_queries, 0, sizeof(r_queries));
4132 r_qwskincache = NULL;
4133 r_qwskincache_size = 0;
4135 // due to caching of texture_t references, the collision cache must be reset
4136 Collision_Cache_Reset(true);
4138 // set up r_skinframe loading system for textures
4139 memset(&r_skinframe, 0, sizeof(r_skinframe));
4140 r_skinframe.loadsequence = 1;
4141 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4143 r_main_texturepool = R_AllocTexturePool();
4144 R_BuildBlankTextures();
4146 if (vid.support.arb_texture_cube_map)
4149 R_BuildNormalizationCube();
4151 r_texture_fogattenuation = NULL;
4152 r_texture_fogheighttexture = NULL;
4153 r_texture_gammaramps = NULL;
4154 //r_texture_fogintensity = NULL;
4155 memset(&r_fb, 0, sizeof(r_fb));
4156 r_glsl_permutation = NULL;
4157 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4158 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4160 r_hlsl_permutation = NULL;
4161 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4162 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4164 memset(&r_svbsp, 0, sizeof (r_svbsp));
4166 memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4167 r_texture_numcubemaps = 0;
4169 r_refdef.fogmasktable_density = 0;
4172 // For Steelstorm Android
4173 // FIXME CACHE the program and reload
4174 // FIXME see possible combinations for SS:BR android
4175 Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
4176 R_SetupShader_SetPermutationGLSL(0, 12);
4177 R_SetupShader_SetPermutationGLSL(0, 13);
4178 R_SetupShader_SetPermutationGLSL(0, 8388621);
4179 R_SetupShader_SetPermutationGLSL(3, 0);
4180 R_SetupShader_SetPermutationGLSL(3, 2048);
4181 R_SetupShader_SetPermutationGLSL(5, 0);
4182 R_SetupShader_SetPermutationGLSL(5, 2);
4183 R_SetupShader_SetPermutationGLSL(5, 2048);
4184 R_SetupShader_SetPermutationGLSL(5, 8388608);
4185 R_SetupShader_SetPermutationGLSL(11, 1);
4186 R_SetupShader_SetPermutationGLSL(11, 2049);
4187 R_SetupShader_SetPermutationGLSL(11, 8193);
4188 R_SetupShader_SetPermutationGLSL(11, 10241);
4189 Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
4193 static void gl_main_shutdown(void)
4196 R_FrameData_Reset();
4197 R_BufferData_Reset();
4199 R_Main_FreeViewCache();
4201 switch(vid.renderpath)
4203 case RENDERPATH_GL11:
4204 case RENDERPATH_GL13:
4205 case RENDERPATH_GL20:
4206 case RENDERPATH_GLES1:
4207 case RENDERPATH_GLES2:
4208 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
4210 qglDeleteQueriesARB(r_maxqueries, r_queries);
4213 case RENDERPATH_D3D9:
4214 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4216 case RENDERPATH_D3D10:
4217 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4219 case RENDERPATH_D3D11:
4220 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4222 case RENDERPATH_SOFT:
4228 memset(r_queries, 0, sizeof(r_queries));
4230 r_qwskincache = NULL;
4231 r_qwskincache_size = 0;
4233 // clear out the r_skinframe state
4234 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4235 memset(&r_skinframe, 0, sizeof(r_skinframe));
4238 Mem_Free(r_svbsp.nodes);
4239 memset(&r_svbsp, 0, sizeof (r_svbsp));
4240 R_FreeTexturePool(&r_main_texturepool);
4241 loadingscreentexture = NULL;
4242 r_texture_blanknormalmap = NULL;
4243 r_texture_white = NULL;
4244 r_texture_grey128 = NULL;
4245 r_texture_black = NULL;
4246 r_texture_whitecube = NULL;
4247 r_texture_normalizationcube = NULL;
4248 r_texture_fogattenuation = NULL;
4249 r_texture_fogheighttexture = NULL;
4250 r_texture_gammaramps = NULL;
4251 r_texture_numcubemaps = 0;
4252 //r_texture_fogintensity = NULL;
4253 memset(&r_fb, 0, sizeof(r_fb));
4256 r_glsl_permutation = NULL;
4257 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4258 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4260 r_hlsl_permutation = NULL;
4261 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4262 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4266 static void gl_main_newmap(void)
4268 // FIXME: move this code to client
4269 char *entities, entname[MAX_QPATH];
4271 Mem_Free(r_qwskincache);
4272 r_qwskincache = NULL;
4273 r_qwskincache_size = 0;
4276 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4277 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4279 CL_ParseEntityLump(entities);
4283 if (cl.worldmodel->brush.entities)
4284 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4286 R_Main_FreeViewCache();
4288 R_FrameData_Reset();
4289 R_BufferData_Reset();
4292 void GL_Main_Init(void)
4295 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4296 R_InitShaderModeInfo();
4298 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4299 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4300 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4301 if (gamemode == GAME_NEHAHRA)
4303 Cvar_RegisterVariable (&gl_fogenable);
4304 Cvar_RegisterVariable (&gl_fogdensity);
4305 Cvar_RegisterVariable (&gl_fogred);
4306 Cvar_RegisterVariable (&gl_foggreen);
4307 Cvar_RegisterVariable (&gl_fogblue);
4308 Cvar_RegisterVariable (&gl_fogstart);
4309 Cvar_RegisterVariable (&gl_fogend);
4310 Cvar_RegisterVariable (&gl_skyclip);
4312 Cvar_RegisterVariable(&r_motionblur);
4313 Cvar_RegisterVariable(&r_damageblur);
4314 Cvar_RegisterVariable(&r_motionblur_averaging);
4315 Cvar_RegisterVariable(&r_motionblur_randomize);
4316 Cvar_RegisterVariable(&r_motionblur_minblur);
4317 Cvar_RegisterVariable(&r_motionblur_maxblur);
4318 Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4319 Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4320 Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4321 Cvar_RegisterVariable(&r_motionblur_mousefactor);
4322 Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4323 Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4324 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4325 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4326 Cvar_RegisterVariable(&r_equalize_entities_by);
4327 Cvar_RegisterVariable(&r_equalize_entities_to);
4328 Cvar_RegisterVariable(&r_depthfirst);
4329 Cvar_RegisterVariable(&r_useinfinitefarclip);
4330 Cvar_RegisterVariable(&r_farclip_base);
4331 Cvar_RegisterVariable(&r_farclip_world);
4332 Cvar_RegisterVariable(&r_nearclip);
4333 Cvar_RegisterVariable(&r_deformvertexes);
4334 Cvar_RegisterVariable(&r_transparent);
4335 Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4336 Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4337 Cvar_RegisterVariable(&r_transparent_useplanardistance);
4338 Cvar_RegisterVariable(&r_showoverdraw);
4339 Cvar_RegisterVariable(&r_showbboxes);
4340 Cvar_RegisterVariable(&r_showsurfaces);
4341 Cvar_RegisterVariable(&r_showtris);
4342 Cvar_RegisterVariable(&r_shownormals);
4343 Cvar_RegisterVariable(&r_showlighting);
4344 Cvar_RegisterVariable(&r_showshadowvolumes);
4345 Cvar_RegisterVariable(&r_showcollisionbrushes);
4346 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4347 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4348 Cvar_RegisterVariable(&r_showdisabledepthtest);
4349 Cvar_RegisterVariable(&r_drawportals);
4350 Cvar_RegisterVariable(&r_drawentities);
4351 Cvar_RegisterVariable(&r_draw2d);
4352 Cvar_RegisterVariable(&r_drawworld);
4353 Cvar_RegisterVariable(&r_cullentities_trace);
4354 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4355 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4356 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4357 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4358 Cvar_RegisterVariable(&r_sortentities);
4359 Cvar_RegisterVariable(&r_drawviewmodel);
4360 Cvar_RegisterVariable(&r_drawexteriormodel);
4361 Cvar_RegisterVariable(&r_speeds);
4362 Cvar_RegisterVariable(&r_fullbrights);
4363 Cvar_RegisterVariable(&r_wateralpha);
4364 Cvar_RegisterVariable(&r_dynamic);
4365 Cvar_RegisterVariable(&r_fakelight);
4366 Cvar_RegisterVariable(&r_fakelight_intensity);
4367 Cvar_RegisterVariable(&r_fullbright);
4368 Cvar_RegisterVariable(&r_shadows);
4369 Cvar_RegisterVariable(&r_shadows_darken);
4370 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4371 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4372 Cvar_RegisterVariable(&r_shadows_throwdistance);
4373 Cvar_RegisterVariable(&r_shadows_throwdirection);
4374 Cvar_RegisterVariable(&r_shadows_focus);
4375 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4376 Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4377 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4378 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4379 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4380 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4381 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4382 Cvar_RegisterVariable(&r_fog_exp2);
4383 Cvar_RegisterVariable(&r_fog_clear);
4384 Cvar_RegisterVariable(&r_drawfog);
4385 Cvar_RegisterVariable(&r_transparentdepthmasking);
4386 Cvar_RegisterVariable(&r_transparent_sortmindist);
4387 Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4388 Cvar_RegisterVariable(&r_transparent_sortarraysize);
4389 Cvar_RegisterVariable(&r_texture_dds_load);
4390 Cvar_RegisterVariable(&r_texture_dds_save);
4391 Cvar_RegisterVariable(&r_textureunits);
4392 Cvar_RegisterVariable(&gl_combine);
4393 Cvar_RegisterVariable(&r_usedepthtextures);
4394 Cvar_RegisterVariable(&r_viewfbo);
4395 Cvar_RegisterVariable(&r_viewscale);
4396 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4397 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4398 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4399 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4400 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4401 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4402 Cvar_RegisterVariable(&r_glsl);
4403 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4404 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4405 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4406 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4407 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4408 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4409 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4410 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4411 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4412 Cvar_RegisterVariable(&r_glsl_postprocess);
4413 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4414 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4415 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4416 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4417 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4418 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4419 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4420 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4421 Cvar_RegisterVariable(&r_celshading);
4422 Cvar_RegisterVariable(&r_celoutlines);
4424 Cvar_RegisterVariable(&r_water);
4425 Cvar_RegisterVariable(&r_water_cameraentitiesonly);
4426 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4427 Cvar_RegisterVariable(&r_water_clippingplanebias);
4428 Cvar_RegisterVariable(&r_water_refractdistort);
4429 Cvar_RegisterVariable(&r_water_reflectdistort);
4430 Cvar_RegisterVariable(&r_water_scissormode);
4431 Cvar_RegisterVariable(&r_water_lowquality);
4432 Cvar_RegisterVariable(&r_water_hideplayer);
4433 Cvar_RegisterVariable(&r_water_fbo);
4435 Cvar_RegisterVariable(&r_lerpsprites);
4436 Cvar_RegisterVariable(&r_lerpmodels);
4437 Cvar_RegisterVariable(&r_lerplightstyles);
4438 Cvar_RegisterVariable(&r_waterscroll);
4439 Cvar_RegisterVariable(&r_bloom);
4440 Cvar_RegisterVariable(&r_bloom_colorscale);
4441 Cvar_RegisterVariable(&r_bloom_brighten);
4442 Cvar_RegisterVariable(&r_bloom_blur);
4443 Cvar_RegisterVariable(&r_bloom_resolution);
4444 Cvar_RegisterVariable(&r_bloom_colorexponent);
4445 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4446 Cvar_RegisterVariable(&r_bloom_scenebrightness);
4447 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4448 Cvar_RegisterVariable(&r_hdr_glowintensity);
4449 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4450 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4451 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4452 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4453 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4454 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4455 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4456 Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4457 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4458 Cvar_RegisterVariable(&developer_texturelogging);
4459 Cvar_RegisterVariable(&gl_lightmaps);
4460 Cvar_RegisterVariable(&r_test);
4461 Cvar_RegisterVariable(&r_batch_multidraw);
4462 Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4463 Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4464 Cvar_RegisterVariable(&r_glsl_skeletal);
4465 Cvar_RegisterVariable(&r_glsl_saturation);
4466 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4467 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4468 Cvar_RegisterVariable(&r_framedatasize);
4469 for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4470 Cvar_RegisterVariable(&r_buffermegs[i]);
4471 Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4472 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4473 Cvar_SetValue("r_fullbrights", 0);
4474 #ifdef DP_MOBILETOUCH
4475 // GLES devices have terrible depth precision in general, so...
4476 Cvar_SetValueQuick(&r_nearclip, 4);
4477 Cvar_SetValueQuick(&r_farclip_base, 4096);
4478 Cvar_SetValueQuick(&r_farclip_world, 0);
4479 Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
4481 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4484 void Render_Init(void)
4497 R_LightningBeams_Init();
4507 extern char *ENGINE_EXTENSIONS;
4510 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4511 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4512 gl_version = (const char *)qglGetString(GL_VERSION);
4513 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4517 if (!gl_platformextensions)
4518 gl_platformextensions = "";
4520 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4521 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4522 Con_Printf("GL_VERSION: %s\n", gl_version);
4523 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4524 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4526 VID_CheckExtensions();
4528 // LordHavoc: report supported extensions
4530 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4532 Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
4535 // clear to black (loading plaque will be seen over this)
4536 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4540 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4544 if (r_trippy.integer)
4546 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4548 p = r_refdef.view.frustum + i;
4553 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4557 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4561 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4565 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4569 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4573 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4577 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4581 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4589 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4593 if (r_trippy.integer)
4595 for (i = 0;i < numplanes;i++)
4602 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4606 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4610 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4614 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4618 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4622 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4626 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4630 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4638 //==================================================================================
4640 // LordHavoc: this stores temporary data used within the same frame
4642 typedef struct r_framedata_mem_s
4644 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4645 size_t size; // how much usable space
4646 size_t current; // how much space in use
4647 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4648 size_t wantedsize; // how much space was allocated
4649 unsigned char *data; // start of real data (16byte aligned)
4653 static r_framedata_mem_t *r_framedata_mem;
4655 void R_FrameData_Reset(void)
4657 while (r_framedata_mem)
4659 r_framedata_mem_t *next = r_framedata_mem->purge;
4660 Mem_Free(r_framedata_mem);
4661 r_framedata_mem = next;
4665 static void R_FrameData_Resize(qboolean mustgrow)
4668 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4669 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4670 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4672 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4673 newmem->wantedsize = wantedsize;
4674 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4675 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4676 newmem->current = 0;
4678 newmem->purge = r_framedata_mem;
4679 r_framedata_mem = newmem;
4683 void R_FrameData_NewFrame(void)
4685 R_FrameData_Resize(false);
4686 if (!r_framedata_mem)
4688 // if we ran out of space on the last frame, free the old memory now
4689 while (r_framedata_mem->purge)
4691 // repeatedly remove the second item in the list, leaving only head
4692 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4693 Mem_Free(r_framedata_mem->purge);
4694 r_framedata_mem->purge = next;
4696 // reset the current mem pointer
4697 r_framedata_mem->current = 0;
4698 r_framedata_mem->mark = 0;
4701 void *R_FrameData_Alloc(size_t size)
4706 // align to 16 byte boundary - the data pointer is already aligned, so we
4707 // only need to ensure the size of every allocation is also aligned
4708 size = (size + 15) & ~15;
4710 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4712 // emergency - we ran out of space, allocate more memory
4713 // note: this has no upper-bound, we'll fail to allocate memory eventually and just die
4714 newvalue = r_framedatasize.value * 2.0f;
4715 // 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
4716 if (sizeof(size_t) >= 8)
4717 newvalue = bound(0.25f, newvalue, (float)(1ll << 42));
4719 newvalue = bound(0.25f, newvalue, (float)(1 << 10));
4720 // this might not be a growing it, but we'll allocate another buffer every time
4721 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4722 R_FrameData_Resize(true);
4725 data = r_framedata_mem->data + r_framedata_mem->current;
4726 r_framedata_mem->current += size;
4728 // count the usage for stats
4729 r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4730 r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4732 return (void *)data;
4735 void *R_FrameData_Store(size_t size, void *data)
4737 void *d = R_FrameData_Alloc(size);
4739 memcpy(d, data, size);
4743 void R_FrameData_SetMark(void)
4745 if (!r_framedata_mem)
4747 r_framedata_mem->mark = r_framedata_mem->current;
4750 void R_FrameData_ReturnToMark(void)
4752 if (!r_framedata_mem)
4754 r_framedata_mem->current = r_framedata_mem->mark;
4757 //==================================================================================
4759 // avoid reusing the same buffer objects on consecutive frames
4760 #define R_BUFFERDATA_CYCLE 3
4762 typedef struct r_bufferdata_buffer_s
4764 struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4765 size_t size; // how much usable space
4766 size_t current; // how much space in use
4767 r_meshbuffer_t *buffer; // the buffer itself
4769 r_bufferdata_buffer_t;
4771 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4772 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4774 /// frees all dynamic buffers
4775 void R_BufferData_Reset(void)
4778 r_bufferdata_buffer_t **p, *mem;
4779 for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4781 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4784 p = &r_bufferdata_buffer[cycle][type];
4790 R_Mesh_DestroyMeshBuffer(mem->buffer);
4797 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4798 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4800 r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4802 float newvalue = r_buffermegs[type].value;
4804 // increase the cvar if we have to (but only if we already have a mem)
4805 if (mustgrow && mem)
4807 newvalue = bound(0.25f, newvalue, 256.0f);
4808 while (newvalue * 1024*1024 < minsize)
4811 // clamp the cvar to valid range
4812 newvalue = bound(0.25f, newvalue, 256.0f);
4813 if (r_buffermegs[type].value != newvalue)
4814 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4816 // calculate size in bytes
4817 size = (size_t)(newvalue * 1024*1024);
4818 size = bound(131072, size, 256*1024*1024);
4820 // allocate a new buffer if the size is different (purge old one later)
4821 // or if we were told we must grow the buffer
4822 if (!mem || mem->size != size || mustgrow)
4824 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4827 if (type == R_BUFFERDATA_VERTEX)
4828 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4829 else if (type == R_BUFFERDATA_INDEX16)
4830 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4831 else if (type == R_BUFFERDATA_INDEX32)
4832 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4833 else if (type == R_BUFFERDATA_UNIFORM)
4834 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4835 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4836 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4840 void R_BufferData_NewFrame(void)
4843 r_bufferdata_buffer_t **p, *mem;
4844 // cycle to the next frame's buffers
4845 r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4846 // if we ran out of space on the last time we used these buffers, free the old memory now
4847 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4849 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4851 R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4852 // free all but the head buffer, this is how we recycle obsolete
4853 // buffers after they are no longer in use
4854 p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4860 R_Mesh_DestroyMeshBuffer(mem->buffer);
4863 // reset the current offset
4864 r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4869 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4871 r_bufferdata_buffer_t *mem;
4875 *returnbufferoffset = 0;
4877 // align size to a byte boundary appropriate for the buffer type, this
4878 // makes all allocations have aligned start offsets
4879 if (type == R_BUFFERDATA_UNIFORM)
4880 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4882 padsize = (datasize + 15) & ~15;
4884 // if we ran out of space in this buffer we must allocate a new one
4885 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)
4886 R_BufferData_Resize(type, true, padsize);
4888 // if the resize did not give us enough memory, fail
4889 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)
4890 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4892 mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4893 offset = (int)mem->current;
4894 mem->current += padsize;
4896 // upload the data to the buffer at the chosen offset
4898 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4899 R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4901 // count the usage for stats
4902 r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4903 r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4905 // return the buffer offset
4906 *returnbufferoffset = offset;
4911 //==================================================================================
4913 // LordHavoc: animcache originally written by Echon, rewritten since then
4916 * Animation cache prevents re-generating mesh data for an animated model
4917 * multiple times in one frame for lighting, shadowing, reflections, etc.
4920 void R_AnimCache_Free(void)
4924 void R_AnimCache_ClearCache(void)
4927 entity_render_t *ent;
4929 for (i = 0;i < r_refdef.scene.numentities;i++)
4931 ent = r_refdef.scene.entities[i];
4932 ent->animcache_vertex3f = NULL;
4933 ent->animcache_vertex3f_vertexbuffer = NULL;
4934 ent->animcache_vertex3f_bufferoffset = 0;
4935 ent->animcache_normal3f = NULL;
4936 ent->animcache_normal3f_vertexbuffer = NULL;
4937 ent->animcache_normal3f_bufferoffset = 0;
4938 ent->animcache_svector3f = NULL;
4939 ent->animcache_svector3f_vertexbuffer = NULL;
4940 ent->animcache_svector3f_bufferoffset = 0;
4941 ent->animcache_tvector3f = NULL;
4942 ent->animcache_tvector3f_vertexbuffer = NULL;
4943 ent->animcache_tvector3f_bufferoffset = 0;
4944 ent->animcache_vertexmesh = NULL;
4945 ent->animcache_vertexmesh_vertexbuffer = NULL;
4946 ent->animcache_vertexmesh_bufferoffset = 0;
4947 ent->animcache_skeletaltransform3x4 = NULL;
4948 ent->animcache_skeletaltransform3x4buffer = NULL;
4949 ent->animcache_skeletaltransform3x4offset = 0;
4950 ent->animcache_skeletaltransform3x4size = 0;
4954 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4958 // check if we need the meshbuffers
4959 if (!vid.useinterleavedarrays)
4962 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4963 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4964 // TODO: upload vertexbuffer?
4965 if (ent->animcache_vertexmesh)
4967 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4968 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4969 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4970 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4971 for (i = 0;i < numvertices;i++)
4972 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4973 if (ent->animcache_svector3f)
4974 for (i = 0;i < numvertices;i++)
4975 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4976 if (ent->animcache_tvector3f)
4977 for (i = 0;i < numvertices;i++)
4978 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4979 if (ent->animcache_normal3f)
4980 for (i = 0;i < numvertices;i++)
4981 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4985 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4987 dp_model_t *model = ent->model;
4990 // see if this ent is worth caching
4991 if (!model || !model->Draw || !model->AnimateVertices)
4993 // nothing to cache if it contains no animations and has no skeleton
4994 if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4996 // see if it is already cached for gpuskeletal
4997 if (ent->animcache_skeletaltransform3x4)
4999 // see if it is already cached as a mesh
5000 if (ent->animcache_vertex3f)
5002 // check if we need to add normals or tangents
5003 if (ent->animcache_normal3f)
5004 wantnormals = false;
5005 if (ent->animcache_svector3f)
5006 wanttangents = false;
5007 if (!wantnormals && !wanttangents)
5011 // check which kind of cache we need to generate
5012 if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
5014 // cache the skeleton so the vertex shader can use it
5015 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
5016 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
5017 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
5018 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
5019 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4);
5020 // note: this can fail if the buffer is at the grow limit
5021 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
5022 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
5024 else if (ent->animcache_vertex3f)
5026 // mesh was already cached but we may need to add normals/tangents
5027 // (this only happens with multiple views, reflections, cameras, etc)
5028 if (wantnormals || wanttangents)
5030 numvertices = model->surfmesh.num_vertices;
5032 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5035 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5036 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5038 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
5039 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5040 r_refdef.stats[r_stat_animcache_shade_count] += 1;
5041 r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5042 r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5047 // generate mesh cache
5048 numvertices = model->surfmesh.num_vertices;
5049 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5051 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5054 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5055 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5057 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
5058 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5059 if (wantnormals || wanttangents)
5061 r_refdef.stats[r_stat_animcache_shade_count] += 1;
5062 r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5063 r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5065 r_refdef.stats[r_stat_animcache_shape_count] += 1;
5066 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
5067 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
5072 void R_AnimCache_CacheVisibleEntities(void)
5075 qboolean wantnormals = true;
5076 qboolean wanttangents = !r_showsurfaces.integer;
5078 switch(vid.renderpath)
5080 case RENDERPATH_GL20:
5081 case RENDERPATH_D3D9:
5082 case RENDERPATH_D3D10:
5083 case RENDERPATH_D3D11:
5084 case RENDERPATH_GLES2:
5086 case RENDERPATH_GL11:
5087 case RENDERPATH_GL13:
5088 case RENDERPATH_GLES1:
5089 wanttangents = false;
5091 case RENDERPATH_SOFT:
5095 if (r_shownormals.integer)
5096 wanttangents = wantnormals = true;
5098 // TODO: thread this
5099 // NOTE: R_PrepareRTLights() also caches entities
5101 for (i = 0;i < r_refdef.scene.numentities;i++)
5102 if (r_refdef.viewcache.entityvisible[i])
5103 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5106 //==================================================================================
5108 extern cvar_t r_overheadsprites_pushback;
5110 static void R_View_UpdateEntityLighting (void)
5113 entity_render_t *ent;
5114 vec3_t tempdiffusenormal, avg;
5115 vec_t f, fa, fd, fdd;
5116 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
5118 for (i = 0;i < r_refdef.scene.numentities;i++)
5120 ent = r_refdef.scene.entities[i];
5122 // skip unseen models
5123 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
5127 if (ent->model && ent->model == cl.worldmodel)
5129 // TODO: use modellight for r_ambient settings on world?
5130 VectorSet(ent->modellight_ambient, 0, 0, 0);
5131 VectorSet(ent->modellight_diffuse, 0, 0, 0);
5132 VectorSet(ent->modellight_lightdir, 0, 0, 1);
5136 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
5138 // aleady updated by CSQC
5139 // TODO: force modellight on BSP models in this case?
5140 VectorCopy(ent->modellight_lightdir, tempdiffusenormal);
5144 // fetch the lighting from the worldmodel data
5145 VectorClear(ent->modellight_ambient);
5146 VectorClear(ent->modellight_diffuse);
5147 VectorClear(tempdiffusenormal);
5148 if (ent->flags & RENDER_LIGHT)
5151 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5153 // complete lightning for lit sprites
5154 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
5155 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
5157 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
5158 org[2] = org[2] + r_overheadsprites_pushback.value;
5159 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5162 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
5164 if(ent->flags & RENDER_EQUALIZE)
5166 // first fix up ambient lighting...
5167 if(r_equalize_entities_minambient.value > 0)
5169 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5172 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
5173 if(fa < r_equalize_entities_minambient.value * fd)
5176 // fa'/fd' = minambient
5177 // fa'+0.25*fd' = fa+0.25*fd
5179 // fa' = fd' * minambient
5180 // fd'*(0.25+minambient) = fa+0.25*fd
5182 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
5183 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
5185 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
5186 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
5187 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
5188 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
5193 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
5195 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
5196 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5200 // adjust brightness and saturation to target
5201 avg[0] = avg[1] = avg[2] = fa / f;
5202 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
5203 avg[0] = avg[1] = avg[2] = fd / f;
5204 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
5210 VectorSet(ent->modellight_ambient, 1, 1, 1);
5213 // move the light direction into modelspace coordinates for lighting code
5214 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
5215 if(VectorLength2(ent->modellight_lightdir) == 0)
5216 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
5217 VectorNormalize(ent->modellight_lightdir);
5221 #define MAX_LINEOFSIGHTTRACES 64
5223 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5226 vec3_t boxmins, boxmaxs;
5229 dp_model_t *model = r_refdef.scene.worldmodel;
5231 if (!model || !model->brush.TraceLineOfSight)
5234 // expand the box a little
5235 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
5236 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
5237 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
5238 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
5239 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
5240 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
5242 // return true if eye is inside enlarged box
5243 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
5247 VectorCopy(eye, start);
5248 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
5249 if (model->brush.TraceLineOfSight(model, start, end))
5252 // try various random positions
5253 for (i = 0;i < numsamples;i++)
5255 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5256 if (model->brush.TraceLineOfSight(model, start, end))
5264 static void R_View_UpdateEntityVisible (void)
5269 entity_render_t *ent;
5271 if (r_refdef.envmap || r_fb.water.hideplayer)
5272 renderimask = RENDER_EXTERIORMODEL | RENDER_VIEWMODEL;
5273 else if (chase_active.integer || r_fb.water.renderingscene)
5274 renderimask = RENDER_VIEWMODEL;
5276 renderimask = RENDER_EXTERIORMODEL;
5277 if (!r_drawviewmodel.integer)
5278 renderimask |= RENDER_VIEWMODEL;
5279 if (!r_drawexteriormodel.integer)
5280 renderimask |= RENDER_EXTERIORMODEL;
5281 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5282 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5284 // worldmodel can check visibility
5285 for (i = 0;i < r_refdef.scene.numentities;i++)
5287 ent = r_refdef.scene.entities[i];
5288 if (!(ent->flags & renderimask))
5289 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)))
5290 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))
5291 r_refdef.viewcache.entityvisible[i] = true;
5296 // no worldmodel or it can't check visibility
5297 for (i = 0;i < r_refdef.scene.numentities;i++)
5299 ent = r_refdef.scene.entities[i];
5300 if (!(ent->flags & renderimask))
5301 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)))
5302 r_refdef.viewcache.entityvisible[i] = true;
5305 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
5306 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
5308 for (i = 0;i < r_refdef.scene.numentities;i++)
5310 if (!r_refdef.viewcache.entityvisible[i])
5312 ent = r_refdef.scene.entities[i];
5313 if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5315 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
5317 continue; // temp entities do pvs only
5318 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5319 ent->last_trace_visibility = realtime;
5320 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5321 r_refdef.viewcache.entityvisible[i] = 0;
5327 /// only used if skyrendermasked, and normally returns false
5328 static int R_DrawBrushModelsSky (void)
5331 entity_render_t *ent;
5334 for (i = 0;i < r_refdef.scene.numentities;i++)
5336 if (!r_refdef.viewcache.entityvisible[i])
5338 ent = r_refdef.scene.entities[i];
5339 if (!ent->model || !ent->model->DrawSky)
5341 ent->model->DrawSky(ent);
5347 static void R_DrawNoModel(entity_render_t *ent);
5348 static void R_DrawModels(void)
5351 entity_render_t *ent;
5353 for (i = 0;i < r_refdef.scene.numentities;i++)
5355 if (!r_refdef.viewcache.entityvisible[i])
5357 ent = r_refdef.scene.entities[i];
5358 r_refdef.stats[r_stat_entities]++;
5360 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5363 Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5364 Con_Printf("R_DrawModels\n");
5365 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]);
5366 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);
5367 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);
5370 if (ent->model && ent->model->Draw != NULL)
5371 ent->model->Draw(ent);
5377 static void R_DrawModelsDepth(void)
5380 entity_render_t *ent;
5382 for (i = 0;i < r_refdef.scene.numentities;i++)
5384 if (!r_refdef.viewcache.entityvisible[i])
5386 ent = r_refdef.scene.entities[i];
5387 if (ent->model && ent->model->DrawDepth != NULL)
5388 ent->model->DrawDepth(ent);
5392 static void R_DrawModelsDebug(void)
5395 entity_render_t *ent;
5397 for (i = 0;i < r_refdef.scene.numentities;i++)
5399 if (!r_refdef.viewcache.entityvisible[i])
5401 ent = r_refdef.scene.entities[i];
5402 if (ent->model && ent->model->DrawDebug != NULL)
5403 ent->model->DrawDebug(ent);
5407 static void R_DrawModelsAddWaterPlanes(void)
5410 entity_render_t *ent;
5412 for (i = 0;i < r_refdef.scene.numentities;i++)
5414 if (!r_refdef.viewcache.entityvisible[i])
5416 ent = r_refdef.scene.entities[i];
5417 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5418 ent->model->DrawAddWaterPlanes(ent);
5422 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}};
5424 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5426 if (r_hdr_irisadaptation.integer)
5431 vec3_t diffusenormal;
5433 vec_t brightness = 0.0f;
5438 VectorCopy(r_refdef.view.forward, forward);
5439 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5441 p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5442 p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5443 p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5444 R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5445 d = DotProduct(forward, diffusenormal);
5446 brightness += VectorLength(ambient);
5448 brightness += d * VectorLength(diffuse);
5450 brightness *= 1.0f / c;
5451 brightness += 0.00001f; // make sure it's never zero
5452 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5453 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5454 current = r_hdr_irisadaptation_value.value;
5456 current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5457 else if (current > goal)
5458 current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5459 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5460 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5462 else if (r_hdr_irisadaptation_value.value != 1.0f)
5463 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5466 static void R_View_SetFrustum(const int *scissor)
5469 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5470 vec3_t forward, left, up, origin, v;
5474 // flipped x coordinates (because x points left here)
5475 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5476 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5478 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5479 switch(vid.renderpath)
5481 case RENDERPATH_D3D9:
5482 case RENDERPATH_D3D10:
5483 case RENDERPATH_D3D11:
5484 // non-flipped y coordinates
5485 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5486 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5488 case RENDERPATH_SOFT:
5489 case RENDERPATH_GL11:
5490 case RENDERPATH_GL13:
5491 case RENDERPATH_GL20:
5492 case RENDERPATH_GLES1:
5493 case RENDERPATH_GLES2:
5494 // non-flipped y coordinates
5495 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5496 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5501 // we can't trust r_refdef.view.forward and friends in reflected scenes
5502 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5505 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5506 r_refdef.view.frustum[0].normal[1] = 0 - 0;
5507 r_refdef.view.frustum[0].normal[2] = -1 - 0;
5508 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5509 r_refdef.view.frustum[1].normal[1] = 0 + 0;
5510 r_refdef.view.frustum[1].normal[2] = -1 + 0;
5511 r_refdef.view.frustum[2].normal[0] = 0 - 0;
5512 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5513 r_refdef.view.frustum[2].normal[2] = -1 - 0;
5514 r_refdef.view.frustum[3].normal[0] = 0 + 0;
5515 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5516 r_refdef.view.frustum[3].normal[2] = -1 + 0;
5520 zNear = r_refdef.nearclip;
5521 nudge = 1.0 - 1.0 / (1<<23);
5522 r_refdef.view.frustum[4].normal[0] = 0 - 0;
5523 r_refdef.view.frustum[4].normal[1] = 0 - 0;
5524 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5525 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5526 r_refdef.view.frustum[5].normal[0] = 0 + 0;
5527 r_refdef.view.frustum[5].normal[1] = 0 + 0;
5528 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5529 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5535 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5536 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5537 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5538 r_refdef.view.frustum[0].dist = m[15] - m[12];
5540 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5541 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5542 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5543 r_refdef.view.frustum[1].dist = m[15] + m[12];
5545 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5546 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5547 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5548 r_refdef.view.frustum[2].dist = m[15] - m[13];
5550 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5551 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5552 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5553 r_refdef.view.frustum[3].dist = m[15] + m[13];
5555 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5556 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5557 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5558 r_refdef.view.frustum[4].dist = m[15] - m[14];
5560 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5561 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5562 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5563 r_refdef.view.frustum[5].dist = m[15] + m[14];
5566 if (r_refdef.view.useperspective)
5568 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5569 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]);
5570 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]);
5571 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]);
5572 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]);
5574 // then the normals from the corners relative to origin
5575 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5576 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5577 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5578 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5580 // in a NORMAL view, forward cross left == up
5581 // in a REFLECTED view, forward cross left == down
5582 // so our cross products above need to be adjusted for a left handed coordinate system
5583 CrossProduct(forward, left, v);
5584 if(DotProduct(v, up) < 0)
5586 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5587 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5588 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5589 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5592 // Leaving those out was a mistake, those were in the old code, and they
5593 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5594 // I couldn't reproduce it after adding those normalizations. --blub
5595 VectorNormalize(r_refdef.view.frustum[0].normal);
5596 VectorNormalize(r_refdef.view.frustum[1].normal);
5597 VectorNormalize(r_refdef.view.frustum[2].normal);
5598 VectorNormalize(r_refdef.view.frustum[3].normal);
5600 // make the corners absolute
5601 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5602 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5603 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5604 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5607 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5609 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5610 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5611 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5612 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5613 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5617 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5618 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5619 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5620 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5621 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5622 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5623 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5624 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5625 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5626 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5628 r_refdef.view.numfrustumplanes = 5;
5630 if (r_refdef.view.useclipplane)
5632 r_refdef.view.numfrustumplanes = 6;
5633 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5636 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5637 PlaneClassify(r_refdef.view.frustum + i);
5639 // LordHavoc: note to all quake engine coders, Quake had a special case
5640 // for 90 degrees which assumed a square view (wrong), so I removed it,
5641 // Quake2 has it disabled as well.
5643 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5644 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5645 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5646 //PlaneClassify(&frustum[0]);
5648 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5649 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5650 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5651 //PlaneClassify(&frustum[1]);
5653 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5654 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5655 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5656 //PlaneClassify(&frustum[2]);
5658 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5659 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5660 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5661 //PlaneClassify(&frustum[3]);
5664 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5665 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5666 //PlaneClassify(&frustum[4]);
5669 static void R_View_UpdateWithScissor(const int *myscissor)
5671 R_Main_ResizeViewCache();
5672 R_View_SetFrustum(myscissor);
5673 R_View_WorldVisibility(r_refdef.view.useclipplane);
5674 R_View_UpdateEntityVisible();
5675 R_View_UpdateEntityLighting();
5678 static void R_View_Update(void)
5680 R_Main_ResizeViewCache();
5681 R_View_SetFrustum(NULL);
5682 R_View_WorldVisibility(r_refdef.view.useclipplane);
5683 R_View_UpdateEntityVisible();
5684 R_View_UpdateEntityLighting();
5687 float viewscalefpsadjusted = 1.0f;
5689 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5691 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5692 scale = bound(0.03125f, scale, 1.0f);
5693 *outwidth = (int)ceil(width * scale);
5694 *outheight = (int)ceil(height * scale);
5697 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5699 const float *customclipplane = NULL;
5701 int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5702 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5704 // LordHavoc: couldn't figure out how to make this approach the
5705 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5706 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5707 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5708 dist = r_refdef.view.clipplane.dist;
5709 plane[0] = r_refdef.view.clipplane.normal[0];
5710 plane[1] = r_refdef.view.clipplane.normal[1];
5711 plane[2] = r_refdef.view.clipplane.normal[2];
5713 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5716 //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5717 rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5719 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5720 if (!r_refdef.view.useperspective)
5721 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);
5722 else if (vid.stencil && r_useinfinitefarclip.integer)
5723 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);
5725 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);
5726 R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5727 R_SetViewport(&r_refdef.view.viewport);
5728 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5730 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5731 float screenplane[4];
5732 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5733 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5734 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5735 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5736 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5740 void R_EntityMatrix(const matrix4x4_t *matrix)
5742 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5744 gl_modelmatrixchanged = false;
5745 gl_modelmatrix = *matrix;
5746 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5747 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5748 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5749 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5751 switch(vid.renderpath)
5753 case RENDERPATH_D3D9:
5755 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5756 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5759 case RENDERPATH_D3D10:
5760 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5762 case RENDERPATH_D3D11:
5763 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5765 case RENDERPATH_GL11:
5766 case RENDERPATH_GL13:
5767 case RENDERPATH_GLES1:
5769 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5772 case RENDERPATH_SOFT:
5773 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5774 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5776 case RENDERPATH_GL20:
5777 case RENDERPATH_GLES2:
5778 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5779 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5785 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5787 r_viewport_t viewport;
5791 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5792 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);
5793 R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5794 R_SetViewport(&viewport);
5795 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5796 GL_Color(1, 1, 1, 1);
5797 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5798 GL_BlendFunc(GL_ONE, GL_ZERO);
5799 GL_ScissorTest(false);
5800 GL_DepthMask(false);
5801 GL_DepthRange(0, 1);
5802 GL_DepthTest(false);
5803 GL_DepthFunc(GL_LEQUAL);
5804 R_EntityMatrix(&identitymatrix);
5805 R_Mesh_ResetTextureState();
5806 GL_PolygonOffset(0, 0);
5807 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5808 switch(vid.renderpath)
5810 case RENDERPATH_GL11:
5811 case RENDERPATH_GL13:
5812 case RENDERPATH_GL20:
5813 case RENDERPATH_GLES1:
5814 case RENDERPATH_GLES2:
5815 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5817 case RENDERPATH_D3D9:
5818 case RENDERPATH_D3D10:
5819 case RENDERPATH_D3D11:
5820 case RENDERPATH_SOFT:
5823 GL_CullFace(GL_NONE);
5828 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5832 R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5835 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5839 R_SetupView(true, fbo, depthtexture, colortexture);
5840 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5841 GL_Color(1, 1, 1, 1);
5842 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5843 GL_BlendFunc(GL_ONE, GL_ZERO);
5844 GL_ScissorTest(true);
5846 GL_DepthRange(0, 1);
5848 GL_DepthFunc(GL_LEQUAL);
5849 R_EntityMatrix(&identitymatrix);
5850 R_Mesh_ResetTextureState();
5851 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5852 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5853 switch(vid.renderpath)
5855 case RENDERPATH_GL11:
5856 case RENDERPATH_GL13:
5857 case RENDERPATH_GL20:
5858 case RENDERPATH_GLES1:
5859 case RENDERPATH_GLES2:
5860 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5862 case RENDERPATH_D3D9:
5863 case RENDERPATH_D3D10:
5864 case RENDERPATH_D3D11:
5865 case RENDERPATH_SOFT:
5868 GL_CullFace(r_refdef.view.cullface_back);
5873 R_RenderView_UpdateViewVectors
5876 void R_RenderView_UpdateViewVectors(void)
5878 // break apart the view matrix into vectors for various purposes
5879 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5880 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5881 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5882 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5883 // make an inverted copy of the view matrix for tracking sprites
5884 Matrix4x4_Invert_Full(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5887 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5888 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5890 static void R_Water_StartFrame(void)
5893 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5894 r_waterstate_waterplane_t *p;
5895 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;
5897 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5900 switch(vid.renderpath)
5902 case RENDERPATH_GL20:
5903 case RENDERPATH_D3D9:
5904 case RENDERPATH_D3D10:
5905 case RENDERPATH_D3D11:
5906 case RENDERPATH_SOFT:
5907 case RENDERPATH_GLES2:
5909 case RENDERPATH_GL11:
5910 case RENDERPATH_GL13:
5911 case RENDERPATH_GLES1:
5915 // set waterwidth and waterheight to the water resolution that will be
5916 // used (often less than the screen resolution for faster rendering)
5917 R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5919 // calculate desired texture sizes
5920 // can't use water if the card does not support the texture size
5921 if (!r_water.integer || r_showsurfaces.integer)
5922 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5923 else if (vid.support.arb_texture_non_power_of_two)
5925 texturewidth = waterwidth;
5926 textureheight = waterheight;
5927 camerawidth = waterwidth;
5928 cameraheight = waterheight;
5932 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5933 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5934 for (camerawidth = 1;camerawidth * 2 <= waterwidth ;camerawidth *= 2);
5935 for (cameraheight = 1;cameraheight * 2 <= waterheight;cameraheight *= 2);
5938 // allocate textures as needed
5939 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))
5941 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5942 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5944 if (p->texture_refraction)
5945 R_FreeTexture(p->texture_refraction);
5946 p->texture_refraction = NULL;
5947 if (p->fbo_refraction)
5948 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5949 p->fbo_refraction = 0;
5950 if (p->texture_reflection)
5951 R_FreeTexture(p->texture_reflection);
5952 p->texture_reflection = NULL;
5953 if (p->fbo_reflection)
5954 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5955 p->fbo_reflection = 0;
5956 if (p->texture_camera)
5957 R_FreeTexture(p->texture_camera);
5958 p->texture_camera = NULL;
5960 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5963 memset(&r_fb.water, 0, sizeof(r_fb.water));
5964 r_fb.water.texturewidth = texturewidth;
5965 r_fb.water.textureheight = textureheight;
5966 r_fb.water.camerawidth = camerawidth;
5967 r_fb.water.cameraheight = cameraheight;
5970 if (r_fb.water.texturewidth)
5972 int scaledwidth, scaledheight;
5974 r_fb.water.enabled = true;
5976 // water resolution is usually reduced
5977 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5978 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5979 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5981 // set up variables that will be used in shader setup
5982 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5983 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5984 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5985 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5988 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5989 r_fb.water.numwaterplanes = 0;
5992 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5994 int planeindex, bestplaneindex, vertexindex;
5995 vec3_t mins, maxs, normal, center, v, n;
5996 vec_t planescore, bestplanescore;
5998 r_waterstate_waterplane_t *p;
5999 texture_t *t = R_GetCurrentTexture(surface->texture);
6001 rsurface.texture = t;
6002 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
6003 // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
6004 if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
6006 // average the vertex normals, find the surface bounds (after deformvertexes)
6007 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
6008 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
6009 VectorCopy(n, normal);
6010 VectorCopy(v, mins);
6011 VectorCopy(v, maxs);
6012 for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
6014 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
6015 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
6016 VectorAdd(normal, n, normal);
6017 mins[0] = min(mins[0], v[0]);
6018 mins[1] = min(mins[1], v[1]);
6019 mins[2] = min(mins[2], v[2]);
6020 maxs[0] = max(maxs[0], v[0]);
6021 maxs[1] = max(maxs[1], v[1]);
6022 maxs[2] = max(maxs[2], v[2]);
6024 VectorNormalize(normal);
6025 VectorMAM(0.5f, mins, 0.5f, maxs, center);
6027 VectorCopy(normal, plane.normal);
6028 VectorNormalize(plane.normal);
6029 plane.dist = DotProduct(center, plane.normal);
6030 PlaneClassify(&plane);
6031 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
6033 // skip backfaces (except if nocullface is set)
6034 // if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
6036 VectorNegate(plane.normal, plane.normal);
6038 PlaneClassify(&plane);
6042 // find a matching plane if there is one
6043 bestplaneindex = -1;
6044 bestplanescore = 1048576.0f;
6045 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6047 if(p->camera_entity == t->camera_entity)
6049 planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
6050 if (bestplaneindex < 0 || bestplanescore > planescore)
6052 bestplaneindex = planeindex;
6053 bestplanescore = planescore;
6057 planeindex = bestplaneindex;
6059 // if this surface does not fit any known plane rendered this frame, add one
6060 if (planeindex < 0 || bestplanescore > 0.001f)
6062 if (r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
6064 // store the new plane
6065 planeindex = r_fb.water.numwaterplanes++;
6066 p = r_fb.water.waterplanes + planeindex;
6068 // clear materialflags and pvs
6069 p->materialflags = 0;
6070 p->pvsvalid = false;
6071 p->camera_entity = t->camera_entity;
6072 VectorCopy(mins, p->mins);
6073 VectorCopy(maxs, p->maxs);
6077 // We're totally screwed.
6083 // merge mins/maxs when we're adding this surface to the plane
6084 p = r_fb.water.waterplanes + planeindex;
6085 p->mins[0] = min(p->mins[0], mins[0]);
6086 p->mins[1] = min(p->mins[1], mins[1]);
6087 p->mins[2] = min(p->mins[2], mins[2]);
6088 p->maxs[0] = max(p->maxs[0], maxs[0]);
6089 p->maxs[1] = max(p->maxs[1], maxs[1]);
6090 p->maxs[2] = max(p->maxs[2], maxs[2]);
6092 // merge this surface's materialflags into the waterplane
6093 p->materialflags |= t->currentmaterialflags;
6094 if(!(p->materialflags & MATERIALFLAG_CAMERA))
6096 // merge this surface's PVS into the waterplane
6097 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6098 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6100 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6106 extern cvar_t r_drawparticles;
6107 extern cvar_t r_drawdecals;
6109 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6112 r_refdef_view_t originalview;
6113 r_refdef_view_t myview;
6114 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;
6115 r_waterstate_waterplane_t *p;
6117 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;
6120 originalview = r_refdef.view;
6122 // lowquality hack, temporarily shut down some cvars and restore afterwards
6123 qualityreduction = r_water_lowquality.integer;
6124 if (qualityreduction > 0)
6126 if (qualityreduction >= 1)
6128 old_r_shadows = r_shadows.integer;
6129 old_r_worldrtlight = r_shadow_realtime_world.integer;
6130 old_r_dlight = r_shadow_realtime_dlight.integer;
6131 Cvar_SetValueQuick(&r_shadows, 0);
6132 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6133 Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6135 if (qualityreduction >= 2)
6137 old_r_dynamic = r_dynamic.integer;
6138 old_r_particles = r_drawparticles.integer;
6139 old_r_decals = r_drawdecals.integer;
6140 Cvar_SetValueQuick(&r_dynamic, 0);
6141 Cvar_SetValueQuick(&r_drawparticles, 0);
6142 Cvar_SetValueQuick(&r_drawdecals, 0);
6146 // make sure enough textures are allocated
6147 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6149 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6151 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6153 if (!p->texture_refraction)
6154 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);
6155 if (!p->texture_refraction)
6159 if (r_fb.water.depthtexture == NULL)
6160 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6161 if (p->fbo_refraction == 0)
6162 p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6165 else if (p->materialflags & MATERIALFLAG_CAMERA)
6167 if (!p->texture_camera)
6168 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);
6169 if (!p->texture_camera)
6173 if (r_fb.water.depthtexture == NULL)
6174 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6175 if (p->fbo_camera == 0)
6176 p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6180 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6182 if (!p->texture_reflection)
6183 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);
6184 if (!p->texture_reflection)
6188 if (r_fb.water.depthtexture == NULL)
6189 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6190 if (p->fbo_reflection == 0)
6191 p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6197 r_refdef.view = originalview;
6198 r_refdef.view.showdebug = false;
6199 r_refdef.view.width = r_fb.water.waterwidth;
6200 r_refdef.view.height = r_fb.water.waterheight;
6201 r_refdef.view.useclipplane = true;
6202 myview = r_refdef.view;
6203 r_fb.water.renderingscene = true;
6204 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6206 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6208 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6210 r_refdef.view = myview;
6211 if(r_water_scissormode.integer)
6213 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6214 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6215 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6218 // render reflected scene and copy into texture
6219 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6220 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6221 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6222 r_refdef.view.clipplane = p->plane;
6223 // reverse the cullface settings for this render
6224 r_refdef.view.cullface_front = GL_FRONT;
6225 r_refdef.view.cullface_back = GL_BACK;
6226 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6228 r_refdef.view.usecustompvs = true;
6230 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6232 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6235 r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
6236 R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6237 R_ClearScreen(r_refdef.fogenabled);
6238 if(r_water_scissormode.integer & 2)
6239 R_View_UpdateWithScissor(myscissor);
6242 R_AnimCache_CacheVisibleEntities();
6243 if(r_water_scissormode.integer & 1)
6244 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6245 R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6247 if (!p->fbo_reflection)
6248 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);
6249 r_fb.water.hideplayer = false;
6252 // render the normal view scene and copy into texture
6253 // (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)
6254 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6256 r_refdef.view = myview;
6257 if(r_water_scissormode.integer)
6259 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6260 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6261 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6264 r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
6266 r_refdef.view.clipplane = p->plane;
6267 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6268 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6270 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6272 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6273 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6274 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6275 R_RenderView_UpdateViewVectors();
6276 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6278 r_refdef.view.usecustompvs = true;
6279 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);
6283 PlaneClassify(&r_refdef.view.clipplane);
6285 R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6286 R_ClearScreen(r_refdef.fogenabled);
6287 if(r_water_scissormode.integer & 2)
6288 R_View_UpdateWithScissor(myscissor);
6291 R_AnimCache_CacheVisibleEntities();
6292 if(r_water_scissormode.integer & 1)
6293 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6294 R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6296 if (!p->fbo_refraction)
6297 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);
6298 r_fb.water.hideplayer = false;
6300 else if (p->materialflags & MATERIALFLAG_CAMERA)
6302 r_refdef.view = myview;
6304 r_refdef.view.clipplane = p->plane;
6305 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6306 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6308 r_refdef.view.width = r_fb.water.camerawidth;
6309 r_refdef.view.height = r_fb.water.cameraheight;
6310 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6311 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6312 r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6313 r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6315 if(p->camera_entity)
6317 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6318 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6321 // note: all of the view is used for displaying... so
6322 // there is no use in scissoring
6324 // reverse the cullface settings for this render
6325 r_refdef.view.cullface_front = GL_FRONT;
6326 r_refdef.view.cullface_back = GL_BACK;
6327 // also reverse the view matrix
6328 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
6329 R_RenderView_UpdateViewVectors();
6330 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6332 r_refdef.view.usecustompvs = true;
6333 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);
6336 // camera needs no clipplane
6337 r_refdef.view.useclipplane = false;
6339 PlaneClassify(&r_refdef.view.clipplane);
6341 r_fb.water.hideplayer = false;
6343 R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6344 R_ClearScreen(r_refdef.fogenabled);
6346 R_AnimCache_CacheVisibleEntities();
6347 R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6350 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);
6351 r_fb.water.hideplayer = false;
6355 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6356 r_fb.water.renderingscene = false;
6357 r_refdef.view = originalview;
6358 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6359 if (!r_fb.water.depthtexture)
6360 R_ClearScreen(r_refdef.fogenabled);
6362 R_AnimCache_CacheVisibleEntities();
6365 r_refdef.view = originalview;
6366 r_fb.water.renderingscene = false;
6367 Cvar_SetValueQuick(&r_water, 0);
6368 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
6370 // lowquality hack, restore cvars
6371 if (qualityreduction > 0)
6373 if (qualityreduction >= 1)
6375 Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6376 Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6377 Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6379 if (qualityreduction >= 2)
6381 Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6382 Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6383 Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6388 static void R_Bloom_StartFrame(void)
6391 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6392 int viewwidth, viewheight;
6393 qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6394 textype_t textype = TEXTYPE_COLORBUFFER;
6396 switch (vid.renderpath)
6398 case RENDERPATH_GL20:
6399 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6400 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6402 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6403 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6406 case RENDERPATH_GL11:
6407 case RENDERPATH_GL13:
6408 case RENDERPATH_GLES1:
6409 case RENDERPATH_GLES2:
6410 case RENDERPATH_D3D9:
6411 case RENDERPATH_D3D10:
6412 case RENDERPATH_D3D11:
6413 r_fb.usedepthtextures = false;
6415 case RENDERPATH_SOFT:
6416 r_fb.usedepthtextures = true;
6420 if (r_viewscale_fpsscaling.integer)
6422 double actualframetime;
6423 double targetframetime;
6425 actualframetime = r_refdef.lastdrawscreentime;
6426 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6427 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6428 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6429 if (r_viewscale_fpsscaling_stepsize.value > 0)
6430 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6431 viewscalefpsadjusted += adjust;
6432 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6435 viewscalefpsadjusted = 1.0f;
6437 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6439 switch(vid.renderpath)
6441 case RENDERPATH_GL20:
6442 case RENDERPATH_D3D9:
6443 case RENDERPATH_D3D10:
6444 case RENDERPATH_D3D11:
6445 case RENDERPATH_SOFT:
6446 case RENDERPATH_GLES2:
6448 case RENDERPATH_GL11:
6449 case RENDERPATH_GL13:
6450 case RENDERPATH_GLES1:
6454 // set bloomwidth and bloomheight to the bloom resolution that will be
6455 // used (often less than the screen resolution for faster rendering)
6456 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6457 r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6458 r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6459 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6460 r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6462 // calculate desired texture sizes
6463 if (vid.support.arb_texture_non_power_of_two)
6465 screentexturewidth = vid.width;
6466 screentextureheight = vid.height;
6467 bloomtexturewidth = r_fb.bloomwidth;
6468 bloomtextureheight = r_fb.bloomheight;
6472 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
6473 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
6474 for (bloomtexturewidth = 1;bloomtexturewidth < r_fb.bloomwidth ;bloomtexturewidth *= 2);
6475 for (bloomtextureheight = 1;bloomtextureheight < r_fb.bloomheight;bloomtextureheight *= 2);
6478 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))
6480 Cvar_SetValueQuick(&r_bloom, 0);
6481 Cvar_SetValueQuick(&r_motionblur, 0);
6482 Cvar_SetValueQuick(&r_damageblur, 0);
6485 if (!((r_glsl_postprocess.integer || r_fxaa.integer) || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6487 && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6489 && r_viewscale.value == 1.0f
6490 && !r_viewscale_fpsscaling.integer)
6491 screentexturewidth = screentextureheight = 0;
6492 if (!r_bloom.integer)
6493 bloomtexturewidth = bloomtextureheight = 0;
6495 // allocate textures as needed
6496 if (r_fb.screentexturewidth != screentexturewidth
6497 || r_fb.screentextureheight != screentextureheight
6498 || r_fb.bloomtexturewidth != bloomtexturewidth
6499 || r_fb.bloomtextureheight != bloomtextureheight
6500 || r_fb.textype != textype
6501 || useviewfbo != (r_fb.fbo != 0))
6503 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6505 if (r_fb.bloomtexture[i])
6506 R_FreeTexture(r_fb.bloomtexture[i]);
6507 r_fb.bloomtexture[i] = NULL;
6509 if (r_fb.bloomfbo[i])
6510 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6511 r_fb.bloomfbo[i] = 0;
6515 R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6518 if (r_fb.colortexture)
6519 R_FreeTexture(r_fb.colortexture);
6520 r_fb.colortexture = NULL;
6522 if (r_fb.depthtexture)
6523 R_FreeTexture(r_fb.depthtexture);
6524 r_fb.depthtexture = NULL;
6526 if (r_fb.ghosttexture)
6527 R_FreeTexture(r_fb.ghosttexture);
6528 r_fb.ghosttexture = NULL;
6530 r_fb.screentexturewidth = screentexturewidth;
6531 r_fb.screentextureheight = screentextureheight;
6532 r_fb.bloomtexturewidth = bloomtexturewidth;
6533 r_fb.bloomtextureheight = bloomtextureheight;
6534 r_fb.textype = textype;
6536 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6538 if (r_motionblur.value > 0 || r_damageblur.value > 0)
6539 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);
6540 r_fb.ghosttexture_valid = false;
6541 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);
6544 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6545 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6546 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6550 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6552 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6554 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);
6556 r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6561 // bloom texture is a different resolution
6562 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6563 r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6564 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6565 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6566 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6568 // set up a texcoord array for the full resolution screen image
6569 // (we have to keep this around to copy back during final render)
6570 r_fb.screentexcoord2f[0] = 0;
6571 r_fb.screentexcoord2f[1] = (float)viewheight / (float)r_fb.screentextureheight;
6572 r_fb.screentexcoord2f[2] = (float)viewwidth / (float)r_fb.screentexturewidth;
6573 r_fb.screentexcoord2f[3] = (float)viewheight / (float)r_fb.screentextureheight;
6574 r_fb.screentexcoord2f[4] = (float)viewwidth / (float)r_fb.screentexturewidth;
6575 r_fb.screentexcoord2f[5] = 0;
6576 r_fb.screentexcoord2f[6] = 0;
6577 r_fb.screentexcoord2f[7] = 0;
6581 for (i = 1;i < 8;i += 2)
6583 r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6587 // set up a texcoord array for the reduced resolution bloom image
6588 // (which will be additive blended over the screen image)
6589 r_fb.bloomtexcoord2f[0] = 0;
6590 r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6591 r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6592 r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6593 r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6594 r_fb.bloomtexcoord2f[5] = 0;
6595 r_fb.bloomtexcoord2f[6] = 0;
6596 r_fb.bloomtexcoord2f[7] = 0;
6598 switch(vid.renderpath)
6600 case RENDERPATH_GL11:
6601 case RENDERPATH_GL13:
6602 case RENDERPATH_GL20:
6603 case RENDERPATH_SOFT:
6604 case RENDERPATH_GLES1:
6605 case RENDERPATH_GLES2:
6607 case RENDERPATH_D3D9:
6608 case RENDERPATH_D3D10:
6609 case RENDERPATH_D3D11:
6610 for (i = 0;i < 4;i++)
6612 r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6613 r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6614 r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6615 r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6620 R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6623 r_refdef.view.clear = true;
6626 static void R_Bloom_MakeTexture(void)
6629 float xoffset, yoffset, r, brighten;
6631 float colorscale = r_bloom_colorscale.value;
6633 r_refdef.stats[r_stat_bloom]++;
6636 // this copy is unnecessary since it happens in R_BlendView already
6639 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);
6640 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6644 // scale down screen texture to the bloom texture size
6646 r_fb.bloomindex = 0;
6647 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6648 R_SetViewport(&r_fb.bloomviewport);
6649 GL_CullFace(GL_NONE);
6650 GL_DepthTest(false);
6651 GL_BlendFunc(GL_ONE, GL_ZERO);
6652 GL_Color(colorscale, colorscale, colorscale, 1);
6653 // 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...
6654 switch(vid.renderpath)
6656 case RENDERPATH_GL11:
6657 case RENDERPATH_GL13:
6658 case RENDERPATH_GL20:
6659 case RENDERPATH_GLES1:
6660 case RENDERPATH_GLES2:
6661 case RENDERPATH_SOFT:
6662 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6664 case RENDERPATH_D3D9:
6665 case RENDERPATH_D3D10:
6666 case RENDERPATH_D3D11:
6667 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6670 // TODO: do boxfilter scale-down in shader?
6671 R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6672 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6673 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6675 // we now have a properly scaled bloom image
6676 if (!r_fb.bloomfbo[r_fb.bloomindex])
6678 // copy it into the bloom texture
6679 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);
6680 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6683 // multiply bloom image by itself as many times as desired
6684 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6686 intex = r_fb.bloomtexture[r_fb.bloomindex];
6687 r_fb.bloomindex ^= 1;
6688 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6690 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6691 if (!r_fb.bloomfbo[r_fb.bloomindex])
6693 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6694 GL_Color(r,r,r,1); // apply fix factor
6699 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6700 GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6701 GL_Color(1,1,1,1); // no fix factor supported here
6703 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6704 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6705 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6706 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6708 if (!r_fb.bloomfbo[r_fb.bloomindex])
6710 // copy the darkened image to a texture
6711 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);
6712 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6716 range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6717 brighten = r_bloom_brighten.value;
6718 brighten = sqrt(brighten);
6720 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6722 for (dir = 0;dir < 2;dir++)
6724 intex = r_fb.bloomtexture[r_fb.bloomindex];
6725 r_fb.bloomindex ^= 1;
6726 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6727 // blend on at multiple vertical offsets to achieve a vertical blur
6728 // TODO: do offset blends using GLSL
6729 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6730 GL_BlendFunc(GL_ONE, GL_ZERO);
6731 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6732 for (x = -range;x <= range;x++)
6734 if (!dir){xoffset = 0;yoffset = x;}
6735 else {xoffset = x;yoffset = 0;}
6736 xoffset /= (float)r_fb.bloomtexturewidth;
6737 yoffset /= (float)r_fb.bloomtextureheight;
6738 // compute a texcoord array with the specified x and y offset
6739 r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6740 r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6741 r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6742 r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6743 r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6744 r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6745 r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6746 r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6747 // this r value looks like a 'dot' particle, fading sharply to
6748 // black at the edges
6749 // (probably not realistic but looks good enough)
6750 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6751 //r = brighten/(range*2+1);
6752 r = brighten / (range * 2 + 1);
6754 r *= (1 - x*x/(float)(range*range));
6755 GL_Color(r, r, r, 1);
6756 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6757 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6758 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6759 GL_BlendFunc(GL_ONE, GL_ONE);
6762 if (!r_fb.bloomfbo[r_fb.bloomindex])
6764 // copy the vertically or horizontally blurred bloom view to a texture
6765 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);
6766 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6771 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6773 unsigned int permutation;
6774 float uservecs[4][4];
6776 R_EntityMatrix(&identitymatrix);
6778 switch (vid.renderpath)
6780 case RENDERPATH_GL20:
6781 case RENDERPATH_D3D9:
6782 case RENDERPATH_D3D10:
6783 case RENDERPATH_D3D11:
6784 case RENDERPATH_SOFT:
6785 case RENDERPATH_GLES2:
6787 (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6788 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6789 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6790 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6791 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6793 if (r_fb.colortexture)
6797 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);
6798 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6801 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6803 // declare variables
6804 float blur_factor, blur_mouseaccel, blur_velocity;
6805 static float blur_average;
6806 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6808 // set a goal for the factoring
6809 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value)
6810 / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6811 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value)
6812 / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6813 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value)
6814 + (blur_mouseaccel * r_motionblur_mousefactor.value));
6816 // from the goal, pick an averaged value between goal and last value
6817 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6818 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6820 // enforce minimum amount of blur
6821 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6823 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6825 // calculate values into a standard alpha
6826 cl.motionbluralpha = 1 - exp(-
6828 (r_motionblur.value * blur_factor / 80)
6830 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6833 max(0.0001, cl.time - cl.oldtime) // fps independent
6836 // randomization for the blur value to combat persistent ghosting
6837 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6838 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6841 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6842 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6844 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6845 GL_Color(1, 1, 1, cl.motionbluralpha);
6846 switch(vid.renderpath)
6848 case RENDERPATH_GL11:
6849 case RENDERPATH_GL13:
6850 case RENDERPATH_GL20:
6851 case RENDERPATH_GLES1:
6852 case RENDERPATH_GLES2:
6853 case RENDERPATH_SOFT:
6854 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6856 case RENDERPATH_D3D9:
6857 case RENDERPATH_D3D10:
6858 case RENDERPATH_D3D11:
6859 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6862 R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6863 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6864 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6867 // updates old view angles for next pass
6868 VectorCopy(cl.viewangles, blur_oldangles);
6870 // copy view into the ghost texture
6871 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);
6872 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6873 r_fb.ghosttexture_valid = true;
6878 // no r_fb.colortexture means we're rendering to the real fb
6879 // we may still have to do view tint...
6880 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6882 // apply a color tint to the whole view
6883 R_ResetViewRendering2D(0, NULL, NULL);
6884 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6885 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6886 R_SetupShader_Generic_NoTexture(false, true);
6887 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6888 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6890 break; // no screen processing, no bloom, skip it
6893 if (r_fb.bloomtexture[0])
6895 // make the bloom texture
6896 R_Bloom_MakeTexture();
6899 #if _MSC_VER >= 1400
6900 #define sscanf sscanf_s
6902 memset(uservecs, 0, sizeof(uservecs));
6903 if (r_glsl_postprocess_uservec1_enable.integer)
6904 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6905 if (r_glsl_postprocess_uservec2_enable.integer)
6906 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6907 if (r_glsl_postprocess_uservec3_enable.integer)
6908 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6909 if (r_glsl_postprocess_uservec4_enable.integer)
6910 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6912 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6913 GL_Color(1, 1, 1, 1);
6914 GL_BlendFunc(GL_ONE, GL_ZERO);
6916 switch(vid.renderpath)
6918 case RENDERPATH_GL20:
6919 case RENDERPATH_GLES2:
6920 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6921 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6922 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_fb.colortexture);
6923 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_fb.bloomtexture[r_fb.bloomindex]);
6924 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6925 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]);
6926 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6927 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]);
6928 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]);
6929 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]);
6930 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]);
6931 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6932 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6933 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);
6935 case RENDERPATH_D3D9:
6937 // 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...
6938 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6939 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6940 R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture);
6941 R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]);
6942 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6943 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6944 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6945 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6946 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6947 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6948 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6949 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6950 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6951 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6954 case RENDERPATH_D3D10:
6955 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6957 case RENDERPATH_D3D11:
6958 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6960 case RENDERPATH_SOFT:
6961 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6962 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6963 R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture);
6964 R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]);
6965 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6966 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6967 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6968 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6969 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6970 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6971 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6972 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6973 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6974 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6979 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6980 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6982 case RENDERPATH_GL11:
6983 case RENDERPATH_GL13:
6984 case RENDERPATH_GLES1:
6985 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6987 // apply a color tint to the whole view
6988 R_ResetViewRendering2D(0, NULL, NULL);
6989 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6990 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6991 R_SetupShader_Generic_NoTexture(false, true);
6992 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6993 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6999 matrix4x4_t r_waterscrollmatrix;
7001 void R_UpdateFog(void)
7004 if (gamemode == GAME_NEHAHRA)
7006 if (gl_fogenable.integer)
7008 r_refdef.oldgl_fogenable = true;
7009 r_refdef.fog_density = gl_fogdensity.value;
7010 r_refdef.fog_red = gl_fogred.value;
7011 r_refdef.fog_green = gl_foggreen.value;
7012 r_refdef.fog_blue = gl_fogblue.value;
7013 r_refdef.fog_alpha = 1;
7014 r_refdef.fog_start = 0;
7015 r_refdef.fog_end = gl_skyclip.value;
7016 r_refdef.fog_height = 1<<30;
7017 r_refdef.fog_fadedepth = 128;
7019 else if (r_refdef.oldgl_fogenable)
7021 r_refdef.oldgl_fogenable = false;
7022 r_refdef.fog_density = 0;
7023 r_refdef.fog_red = 0;
7024 r_refdef.fog_green = 0;
7025 r_refdef.fog_blue = 0;
7026 r_refdef.fog_alpha = 0;
7027 r_refdef.fog_start = 0;
7028 r_refdef.fog_end = 0;
7029 r_refdef.fog_height = 1<<30;
7030 r_refdef.fog_fadedepth = 128;
7035 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
7036 r_refdef.fog_start = max(0, r_refdef.fog_start);
7037 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
7039 if (r_refdef.fog_density && r_drawfog.integer)
7041 r_refdef.fogenabled = true;
7042 // this is the point where the fog reaches 0.9986 alpha, which we
7043 // consider a good enough cutoff point for the texture
7044 // (0.9986 * 256 == 255.6)
7045 if (r_fog_exp2.integer)
7046 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
7048 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
7049 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
7050 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
7051 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
7052 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
7053 R_BuildFogHeightTexture();
7054 // fog color was already set
7055 // update the fog texture
7056 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)
7057 R_BuildFogTexture();
7058 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
7059 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
7062 r_refdef.fogenabled = false;
7065 if (r_refdef.fog_density)
7067 r_refdef.fogcolor[0] = r_refdef.fog_red;
7068 r_refdef.fogcolor[1] = r_refdef.fog_green;
7069 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7071 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7072 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7073 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7074 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7078 VectorCopy(r_refdef.fogcolor, fogvec);
7079 // color.rgb *= ContrastBoost * SceneBrightness;
7080 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7081 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7082 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7083 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7088 void R_UpdateVariables(void)
7092 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7094 r_refdef.farclip = r_farclip_base.value;
7095 if (r_refdef.scene.worldmodel)
7096 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7097 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7099 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7100 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7101 r_refdef.polygonfactor = 0;
7102 r_refdef.polygonoffset = 0;
7103 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7104 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7106 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7107 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7108 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
7109 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7110 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7111 if (FAKELIGHT_ENABLED)
7113 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
7115 else if (r_refdef.scene.worldmodel)
7117 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
7119 if (r_showsurfaces.integer)
7121 r_refdef.scene.rtworld = false;
7122 r_refdef.scene.rtworldshadows = false;
7123 r_refdef.scene.rtdlight = false;
7124 r_refdef.scene.rtdlightshadows = false;
7125 r_refdef.lightmapintensity = 0;
7128 r_gpuskeletal = false;
7129 switch(vid.renderpath)
7131 case RENDERPATH_GL20:
7132 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
7133 case RENDERPATH_D3D9:
7134 case RENDERPATH_D3D10:
7135 case RENDERPATH_D3D11:
7136 case RENDERPATH_SOFT:
7137 case RENDERPATH_GLES2:
7138 if(v_glslgamma.integer && !vid_gammatables_trivial)
7140 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7142 // build GLSL gamma texture
7143 #define RAMPWIDTH 256
7144 unsigned short ramp[RAMPWIDTH * 3];
7145 unsigned char rampbgr[RAMPWIDTH][4];
7148 r_texture_gammaramps_serial = vid_gammatables_serial;
7150 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7151 for(i = 0; i < RAMPWIDTH; ++i)
7153 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7154 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7155 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7158 if (r_texture_gammaramps)
7160 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7164 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7170 // remove GLSL gamma texture
7173 case RENDERPATH_GL11:
7174 case RENDERPATH_GL13:
7175 case RENDERPATH_GLES1:
7180 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7181 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7187 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7188 if( scenetype != r_currentscenetype ) {
7189 // store the old scenetype
7190 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7191 r_currentscenetype = scenetype;
7192 // move in the new scene
7193 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7202 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7204 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7205 if( scenetype == r_currentscenetype ) {
7206 return &r_refdef.scene;
7208 return &r_scenes_store[ scenetype ];
7212 static int R_SortEntities_Compare(const void *ap, const void *bp)
7214 const entity_render_t *a = *(const entity_render_t **)ap;
7215 const entity_render_t *b = *(const entity_render_t **)bp;
7218 if(a->model < b->model)
7220 if(a->model > b->model)
7224 // TODO possibly calculate the REAL skinnum here first using
7226 if(a->skinnum < b->skinnum)
7228 if(a->skinnum > b->skinnum)
7231 // everything we compared is equal
7234 static void R_SortEntities(void)
7236 // below or equal 2 ents, sorting never gains anything
7237 if(r_refdef.scene.numentities <= 2)
7240 qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7248 int dpsoftrast_test;
7249 extern cvar_t r_shadow_bouncegrid;
7250 void R_RenderView(void)
7252 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7254 rtexture_t *depthtexture;
7255 rtexture_t *colortexture;
7257 dpsoftrast_test = r_test.integer;
7259 if (r_timereport_active)
7260 R_TimeReport("start");
7261 r_textureframe++; // used only by R_GetCurrentTexture
7262 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7264 if(R_CompileShader_CheckStaticParms())
7267 if (!r_drawentities.integer)
7268 r_refdef.scene.numentities = 0;
7269 else if (r_sortentities.integer)
7272 R_AnimCache_ClearCache();
7274 /* adjust for stereo display */
7275 if(R_Stereo_Active())
7277 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);
7278 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7281 if (r_refdef.view.isoverlay)
7283 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7284 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7285 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7286 R_TimeReport("depthclear");
7288 r_refdef.view.showdebug = false;
7290 r_fb.water.enabled = false;
7291 r_fb.water.numwaterplanes = 0;
7293 R_RenderScene(0, NULL, NULL);
7295 r_refdef.view.matrix = originalmatrix;
7301 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7303 r_refdef.view.matrix = originalmatrix;
7307 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7309 if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7310 // in sRGB fallback, behave similar to true sRGB: convert this
7311 // value from linear to sRGB
7312 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7314 R_RenderView_UpdateViewVectors();
7316 R_Shadow_UpdateWorldLightSelection();
7318 R_Bloom_StartFrame();
7320 // apply bloom brightness offset
7321 if(r_fb.bloomtexture[0])
7322 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7324 R_Water_StartFrame();
7326 // now we probably have an fbo to render into
7328 depthtexture = r_fb.depthtexture;
7329 colortexture = r_fb.colortexture;
7332 if (r_timereport_active)
7333 R_TimeReport("viewsetup");
7335 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7337 if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7339 R_ClearScreen(r_refdef.fogenabled);
7340 if (r_timereport_active)
7341 R_TimeReport("viewclear");
7343 r_refdef.view.clear = true;
7345 r_refdef.view.showdebug = true;
7348 if (r_timereport_active)
7349 R_TimeReport("visibility");
7351 R_AnimCache_CacheVisibleEntities();
7352 if (r_timereport_active)
7353 R_TimeReport("animcache");
7355 R_Shadow_UpdateBounceGridTexture();
7356 if (r_timereport_active && r_shadow_bouncegrid.integer)
7357 R_TimeReport("bouncegrid");
7359 r_fb.water.numwaterplanes = 0;
7360 if (r_fb.water.enabled)
7361 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7363 R_RenderScene(fbo, depthtexture, colortexture);
7364 r_fb.water.numwaterplanes = 0;
7366 R_BlendView(fbo, depthtexture, colortexture);
7367 if (r_timereport_active)
7368 R_TimeReport("blendview");
7370 GL_Scissor(0, 0, vid.width, vid.height);
7371 GL_ScissorTest(false);
7373 r_refdef.view.matrix = originalmatrix;
7378 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7380 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7382 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7383 if (r_timereport_active)
7384 R_TimeReport("waterworld");
7387 // don't let sound skip if going slow
7388 if (r_refdef.scene.extraupdate)
7391 R_DrawModelsAddWaterPlanes();
7392 if (r_timereport_active)
7393 R_TimeReport("watermodels");
7395 if (r_fb.water.numwaterplanes)
7397 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7398 if (r_timereport_active)
7399 R_TimeReport("waterscenes");
7403 extern cvar_t cl_locs_show;
7404 static void R_DrawLocs(void);
7405 static void R_DrawEntityBBoxes(void);
7406 static void R_DrawModelDecals(void);
7407 extern cvar_t cl_decals_newsystem;
7408 extern qboolean r_shadow_usingdeferredprepass;
7409 extern int r_shadow_shadowmapatlas_modelshadows_size;
7410 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7412 qboolean shadowmapping = false;
7414 if (r_timereport_active)
7415 R_TimeReport("beginscene");
7417 r_refdef.stats[r_stat_renders]++;
7421 // don't let sound skip if going slow
7422 if (r_refdef.scene.extraupdate)
7425 R_MeshQueue_BeginScene();
7429 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);
7431 if (r_timereport_active)
7432 R_TimeReport("skystartframe");
7434 if (cl.csqc_vidvars.drawworld)
7436 // don't let sound skip if going slow
7437 if (r_refdef.scene.extraupdate)
7440 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7442 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7443 if (r_timereport_active)
7444 R_TimeReport("worldsky");
7447 if (R_DrawBrushModelsSky() && r_timereport_active)
7448 R_TimeReport("bmodelsky");
7450 if (skyrendermasked && skyrenderlater)
7452 // we have to force off the water clipping plane while rendering sky
7453 R_SetupView(false, fbo, depthtexture, colortexture);
7455 R_SetupView(true, fbo, depthtexture, colortexture);
7456 if (r_timereport_active)
7457 R_TimeReport("sky");
7461 R_Shadow_PrepareModelShadows();
7462 R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7463 if (r_timereport_active)
7464 R_TimeReport("preparelights");
7466 // render all the shadowmaps that will be used for this view
7467 shadowmapping = R_Shadow_ShadowMappingEnabled();
7468 if (shadowmapping || r_shadow_shadowmapatlas_modelshadows_size)
7470 R_Shadow_DrawShadowMaps();
7471 if (r_timereport_active)
7472 R_TimeReport("shadowmaps");
7475 // render prepass deferred lighting if r_shadow_deferred is on, this produces light buffers that will be sampled in forward pass
7476 if (r_shadow_usingdeferredprepass)
7477 R_Shadow_DrawPrepass();
7479 // now we begin the forward pass of the view render
7480 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7482 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7483 if (r_timereport_active)
7484 R_TimeReport("worlddepth");
7486 if (r_depthfirst.integer >= 2)
7488 R_DrawModelsDepth();
7489 if (r_timereport_active)
7490 R_TimeReport("modeldepth");
7493 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7495 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7496 if (r_timereport_active)
7497 R_TimeReport("world");
7500 // don't let sound skip if going slow
7501 if (r_refdef.scene.extraupdate)
7505 if (r_timereport_active)
7506 R_TimeReport("models");
7508 // don't let sound skip if going slow
7509 if (r_refdef.scene.extraupdate)
7512 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7514 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7515 R_Shadow_DrawModelShadows();
7516 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7517 // don't let sound skip if going slow
7518 if (r_refdef.scene.extraupdate)
7522 if (!r_shadow_usingdeferredprepass)
7524 R_Shadow_DrawLights();
7525 if (r_timereport_active)
7526 R_TimeReport("rtlights");
7529 // don't let sound skip if going slow
7530 if (r_refdef.scene.extraupdate)
7533 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7535 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7536 R_Shadow_DrawModelShadows();
7537 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7538 // don't let sound skip if going slow
7539 if (r_refdef.scene.extraupdate)
7543 if (cl.csqc_vidvars.drawworld)
7545 if (cl_decals_newsystem.integer)
7547 R_DrawModelDecals();
7548 if (r_timereport_active)
7549 R_TimeReport("modeldecals");
7554 if (r_timereport_active)
7555 R_TimeReport("decals");
7559 if (r_timereport_active)
7560 R_TimeReport("particles");
7563 if (r_timereport_active)
7564 R_TimeReport("explosions");
7566 R_DrawLightningBeams();
7567 if (r_timereport_active)
7568 R_TimeReport("lightning");
7572 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7574 if (r_refdef.view.showdebug)
7576 if (cl_locs_show.integer)
7579 if (r_timereport_active)
7580 R_TimeReport("showlocs");
7583 if (r_drawportals.integer)
7586 if (r_timereport_active)
7587 R_TimeReport("portals");
7590 if (r_showbboxes.value > 0)
7592 R_DrawEntityBBoxes();
7593 if (r_timereport_active)
7594 R_TimeReport("bboxes");
7598 if (r_transparent.integer)
7600 R_MeshQueue_RenderTransparent();
7601 if (r_timereport_active)
7602 R_TimeReport("drawtrans");
7605 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))
7607 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7608 if (r_timereport_active)
7609 R_TimeReport("worlddebug");
7610 R_DrawModelsDebug();
7611 if (r_timereport_active)
7612 R_TimeReport("modeldebug");
7615 if (cl.csqc_vidvars.drawworld)
7617 R_Shadow_DrawCoronas();
7618 if (r_timereport_active)
7619 R_TimeReport("coronas");
7624 GL_DepthTest(false);
7625 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7626 GL_Color(1, 1, 1, 1);
7627 qglBegin(GL_POLYGON);
7628 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7629 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7630 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7631 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7633 qglBegin(GL_POLYGON);
7634 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]);
7635 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]);
7636 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]);
7637 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]);
7639 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7643 // don't let sound skip if going slow
7644 if (r_refdef.scene.extraupdate)
7648 static const unsigned short bboxelements[36] =
7658 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7661 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7663 RSurf_ActiveWorldEntity();
7665 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7666 GL_DepthMask(false);
7667 GL_DepthRange(0, 1);
7668 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7669 // R_Mesh_ResetTextureState();
7671 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7672 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7673 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7674 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7675 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7676 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7677 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7678 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7679 R_FillColors(color4f, 8, cr, cg, cb, ca);
7680 if (r_refdef.fogenabled)
7682 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7684 f1 = RSurf_FogVertex(v);
7686 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7687 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7688 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7691 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7692 R_Mesh_ResetTextureState();
7693 R_SetupShader_Generic_NoTexture(false, false);
7694 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7697 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7699 prvm_prog_t *prog = SVVM_prog;
7702 prvm_edict_t *edict;
7704 // this function draws bounding boxes of server entities
7708 GL_CullFace(GL_NONE);
7709 R_SetupShader_Generic_NoTexture(false, false);
7711 for (i = 0;i < numsurfaces;i++)
7713 edict = PRVM_EDICT_NUM(surfacelist[i]);
7714 switch ((int)PRVM_serveredictfloat(edict, solid))
7716 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7717 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7718 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7719 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7720 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7721 case SOLID_CORPSE: Vector4Set(color, 1, 0.5, 0, 0.05);break;
7722 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7724 color[3] *= r_showbboxes.value;
7725 color[3] = bound(0, color[3], 1);
7726 GL_DepthTest(!r_showdisabledepthtest.integer);
7727 GL_CullFace(r_refdef.view.cullface_front);
7728 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7732 static void R_DrawEntityBBoxes(void)
7735 prvm_edict_t *edict;
7737 prvm_prog_t *prog = SVVM_prog;
7739 // this function draws bounding boxes of server entities
7743 for (i = 0;i < prog->num_edicts;i++)
7745 edict = PRVM_EDICT_NUM(i);
7746 if (edict->priv.server->free)
7748 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7749 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7751 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7753 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7754 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7758 static const int nomodelelement3i[24] =
7770 static const unsigned short nomodelelement3s[24] =
7782 static const float nomodelvertex3f[6*3] =
7792 static const float nomodelcolor4f[6*4] =
7794 0.0f, 0.0f, 0.5f, 1.0f,
7795 0.0f, 0.0f, 0.5f, 1.0f,
7796 0.0f, 0.5f, 0.0f, 1.0f,
7797 0.0f, 0.5f, 0.0f, 1.0f,
7798 0.5f, 0.0f, 0.0f, 1.0f,
7799 0.5f, 0.0f, 0.0f, 1.0f
7802 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7808 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);
7810 // this is only called once per entity so numsurfaces is always 1, and
7811 // surfacelist is always {0}, so this code does not handle batches
7813 if (rsurface.ent_flags & RENDER_ADDITIVE)
7815 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7816 GL_DepthMask(false);
7818 else if (rsurface.colormod[3] < 1)
7820 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7821 GL_DepthMask(false);
7825 GL_BlendFunc(GL_ONE, GL_ZERO);
7828 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7829 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7830 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7831 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7832 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7833 for (i = 0, c = color4f;i < 6;i++, c += 4)
7835 c[0] *= rsurface.colormod[0];
7836 c[1] *= rsurface.colormod[1];
7837 c[2] *= rsurface.colormod[2];
7838 c[3] *= rsurface.colormod[3];
7840 if (r_refdef.fogenabled)
7842 for (i = 0, c = color4f;i < 6;i++, c += 4)
7844 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7846 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7847 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7848 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7851 // R_Mesh_ResetTextureState();
7852 R_SetupShader_Generic_NoTexture(false, false);
7853 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7854 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7857 void R_DrawNoModel(entity_render_t *ent)
7860 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7861 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7862 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7864 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7867 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7869 vec3_t right1, right2, diff, normal;
7871 VectorSubtract (org2, org1, normal);
7873 // calculate 'right' vector for start
7874 VectorSubtract (r_refdef.view.origin, org1, diff);
7875 CrossProduct (normal, diff, right1);
7876 VectorNormalize (right1);
7878 // calculate 'right' vector for end
7879 VectorSubtract (r_refdef.view.origin, org2, diff);
7880 CrossProduct (normal, diff, right2);
7881 VectorNormalize (right2);
7883 vert[ 0] = org1[0] + width * right1[0];
7884 vert[ 1] = org1[1] + width * right1[1];
7885 vert[ 2] = org1[2] + width * right1[2];
7886 vert[ 3] = org1[0] - width * right1[0];
7887 vert[ 4] = org1[1] - width * right1[1];
7888 vert[ 5] = org1[2] - width * right1[2];
7889 vert[ 6] = org2[0] - width * right2[0];
7890 vert[ 7] = org2[1] - width * right2[1];
7891 vert[ 8] = org2[2] - width * right2[2];
7892 vert[ 9] = org2[0] + width * right2[0];
7893 vert[10] = org2[1] + width * right2[1];
7894 vert[11] = org2[2] + width * right2[2];
7897 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)
7899 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7900 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7901 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7902 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7903 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7904 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7905 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7906 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7907 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7908 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7909 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7910 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7913 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7918 VectorSet(v, x, y, z);
7919 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7920 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7922 if (i == mesh->numvertices)
7924 if (mesh->numvertices < mesh->maxvertices)
7926 VectorCopy(v, vertex3f);
7927 mesh->numvertices++;
7929 return mesh->numvertices;
7935 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7939 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7940 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7941 e = mesh->element3i + mesh->numtriangles * 3;
7942 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7944 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7945 if (mesh->numtriangles < mesh->maxtriangles)
7950 mesh->numtriangles++;
7952 element[1] = element[2];
7956 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7960 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7961 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7962 e = mesh->element3i + mesh->numtriangles * 3;
7963 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7965 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7966 if (mesh->numtriangles < mesh->maxtriangles)
7971 mesh->numtriangles++;
7973 element[1] = element[2];
7977 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7978 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7980 int planenum, planenum2;
7983 mplane_t *plane, *plane2;
7985 double temppoints[2][256*3];
7986 // figure out how large a bounding box we need to properly compute this brush
7988 for (w = 0;w < numplanes;w++)
7989 maxdist = max(maxdist, fabs(planes[w].dist));
7990 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7991 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7992 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7996 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7997 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7999 if (planenum2 == planenum)
8001 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);
8004 if (tempnumpoints < 3)
8006 // generate elements forming a triangle fan for this polygon
8007 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
8011 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)
8013 texturelayer_t *layer;
8014 layer = t->currentlayers + t->currentnumlayers++;
8016 layer->depthmask = depthmask;
8017 layer->blendfunc1 = blendfunc1;
8018 layer->blendfunc2 = blendfunc2;
8019 layer->texture = texture;
8020 layer->texmatrix = *matrix;
8021 layer->color[0] = r;
8022 layer->color[1] = g;
8023 layer->color[2] = b;
8024 layer->color[3] = a;
8027 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
8029 if(parms[0] == 0 && parms[1] == 0)
8031 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8032 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
8037 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8040 index = parms[2] + rsurface.shadertime * parms[3];
8041 index -= floor(index);
8042 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
8045 case Q3WAVEFUNC_NONE:
8046 case Q3WAVEFUNC_NOISE:
8047 case Q3WAVEFUNC_COUNT:
8050 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8051 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8052 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8053 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8054 case Q3WAVEFUNC_TRIANGLE:
8056 f = index - floor(index);
8069 f = parms[0] + parms[1] * f;
8070 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8071 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
8075 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8082 matrix4x4_t matrix, temp;
8083 // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
8084 // it's better to have one huge fixup every 9 hours than gradual
8085 // degradation over time which looks consistently bad after many hours.
8087 // tcmod scroll in particular suffers from this degradation which can't be
8088 // effectively worked around even with floor() tricks because we don't
8089 // know if tcmod scroll is the last tcmod being applied, and for clampmap
8090 // a workaround involving floor() would be incorrect anyway...
8091 shadertime = rsurface.shadertime;
8092 if (shadertime >= 32768.0f)
8093 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
8094 switch(tcmod->tcmod)
8098 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8099 matrix = r_waterscrollmatrix;
8101 matrix = identitymatrix;
8103 case Q3TCMOD_ENTITYTRANSLATE:
8104 // this is used in Q3 to allow the gamecode to control texcoord
8105 // scrolling on the entity, which is not supported in darkplaces yet.
8106 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8108 case Q3TCMOD_ROTATE:
8109 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8110 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
8111 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8114 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8116 case Q3TCMOD_SCROLL:
8117 // this particular tcmod is a "bug for bug" compatible one with regards to
8118 // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
8119 // specifically did the wrapping and so we must mimic that...
8120 offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
8121 offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
8122 Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
8124 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8125 w = (int) tcmod->parms[0];
8126 h = (int) tcmod->parms[1];
8127 f = rsurface.shadertime / (tcmod->parms[2] * w * h);
8129 idx = (int) floor(f * w * h);
8130 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8132 case Q3TCMOD_STRETCH:
8133 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8134 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8136 case Q3TCMOD_TRANSFORM:
8137 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
8138 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
8139 VectorSet(tcmat + 6, 0 , 0 , 1);
8140 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
8141 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8143 case Q3TCMOD_TURBULENT:
8144 // this is handled in the RSurf_PrepareVertices function
8145 matrix = identitymatrix;
8149 Matrix4x4_Concat(texmatrix, &matrix, &temp);
8152 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8154 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8155 char name[MAX_QPATH];
8156 skinframe_t *skinframe;
8157 unsigned char pixels[296*194];
8158 strlcpy(cache->name, skinname, sizeof(cache->name));
8159 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8160 if (developer_loading.integer)
8161 Con_Printf("loading %s\n", name);
8162 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8163 if (!skinframe || !skinframe->base)
8166 fs_offset_t filesize;
8168 f = FS_LoadFile(name, tempmempool, true, &filesize);
8171 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8172 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8176 cache->skinframe = skinframe;
8179 texture_t *R_GetCurrentTexture(texture_t *t)
8182 const entity_render_t *ent = rsurface.entity;
8183 dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8184 q3shaderinfo_layer_tcmod_t *tcmod;
8186 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8187 return t->currentframe;
8188 t->update_lastrenderframe = r_textureframe;
8189 t->update_lastrenderentity = (void *)ent;
8191 if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8192 t->camera_entity = ent->entitynumber;
8194 t->camera_entity = 0;
8196 // switch to an alternate material if this is a q1bsp animated material
8198 texture_t *texture = t;
8199 int s = rsurface.ent_skinnum;
8200 if ((unsigned int)s >= (unsigned int)model->numskins)
8202 if (model->skinscenes)
8204 if (model->skinscenes[s].framecount > 1)
8205 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8207 s = model->skinscenes[s].firstframe;
8210 t = t + s * model->num_surfaces;
8213 // use an alternate animation if the entity's frame is not 0,
8214 // and only if the texture has an alternate animation
8215 if (t->animated == 2) // q2bsp
8216 t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]];
8217 else if (rsurface.ent_alttextures && t->anim_total[1])
8218 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8220 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8222 texture->currentframe = t;
8225 // update currentskinframe to be a qw skin or animation frame
8226 if (rsurface.ent_qwskin >= 0)
8228 i = rsurface.ent_qwskin;
8229 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8231 r_qwskincache_size = cl.maxclients;
8233 Mem_Free(r_qwskincache);
8234 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8236 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8237 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8238 t->currentskinframe = r_qwskincache[i].skinframe;
8239 if (t->materialshaderpass && t->currentskinframe == NULL)
8240 t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
8242 else if (t->materialshaderpass && t->materialshaderpass->numframes >= 2)
8243 t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
8244 if (t->backgroundshaderpass && t->backgroundshaderpass->numframes >= 2)
8245 t->backgroundcurrentskinframe = t->backgroundshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundshaderpass->framerate, t->backgroundshaderpass->numframes)];
8247 t->currentmaterialflags = t->basematerialflags;
8248 t->currentalpha = rsurface.colormod[3] * t->basealpha;
8249 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8250 t->currentalpha *= r_wateralpha.value;
8251 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8252 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8253 if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8254 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8255 if (!(rsurface.ent_flags & RENDER_LIGHT))
8256 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8257 else if (FAKELIGHT_ENABLED)
8259 // no modellight if using fakelight for the map
8261 else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8263 // pick a model lighting mode
8264 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8265 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8267 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8269 if (rsurface.ent_flags & RENDER_ADDITIVE)
8270 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8271 else if (t->currentalpha < 1)
8272 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8273 // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8274 if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8275 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8276 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8277 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8278 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8279 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8280 if (t->backgroundshaderpass)
8281 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8282 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8284 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8285 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8288 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8289 if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8291 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8292 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8294 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8295 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8297 // there is no tcmod
8298 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8300 t->currenttexmatrix = r_waterscrollmatrix;
8301 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8303 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8305 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8306 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8309 if (t->materialshaderpass)
8310 for (i = 0, tcmod = t->materialshaderpass->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8311 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8313 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8314 if (t->currentskinframe->qpixels)
8315 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8316 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8317 if (!t->basetexture)
8318 t->basetexture = r_texture_notexture;
8319 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8320 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8321 t->nmaptexture = t->currentskinframe->nmap;
8322 if (!t->nmaptexture)
8323 t->nmaptexture = r_texture_blanknormalmap;
8324 t->glosstexture = r_texture_black;
8325 t->glowtexture = t->currentskinframe->glow;
8326 t->fogtexture = t->currentskinframe->fog;
8327 t->reflectmasktexture = t->currentskinframe->reflect;
8328 if (t->backgroundshaderpass)
8330 for (i = 0, tcmod = t->backgroundshaderpass->tcmods; i < Q3MAXTCMODS && tcmod->tcmod; i++, tcmod++)
8331 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8332 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8333 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8334 t->backgroundglosstexture = r_texture_black;
8335 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8336 if (!t->backgroundnmaptexture)
8337 t->backgroundnmaptexture = r_texture_blanknormalmap;
8338 // make sure that if glow is going to be used, both textures are not NULL
8339 if (!t->backgroundglowtexture && t->glowtexture)
8340 t->backgroundglowtexture = r_texture_black;
8341 if (!t->glowtexture && t->backgroundglowtexture)
8342 t->glowtexture = r_texture_black;
8346 t->backgroundbasetexture = r_texture_white;
8347 t->backgroundnmaptexture = r_texture_blanknormalmap;
8348 t->backgroundglosstexture = r_texture_black;
8349 t->backgroundglowtexture = NULL;
8351 t->specularpower = r_shadow_glossexponent.value;
8352 // TODO: store reference values for these in the texture?
8353 t->specularscale = 0;
8354 if (r_shadow_gloss.integer > 0)
8356 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8358 if (r_shadow_glossintensity.value > 0)
8360 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8361 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8362 t->specularscale = r_shadow_glossintensity.value;
8365 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8367 t->glosstexture = r_texture_white;
8368 t->backgroundglosstexture = r_texture_white;
8369 t->specularscale = r_shadow_gloss2intensity.value;
8370 t->specularpower = r_shadow_gloss2exponent.value;
8373 t->specularscale *= t->specularscalemod;
8374 t->specularpower *= t->specularpowermod;
8375 t->rtlightambient = 0;
8377 // lightmaps mode looks bad with dlights using actual texturing, so turn
8378 // off the colormap and glossmap, but leave the normalmap on as it still
8379 // accurately represents the shading involved
8380 if (gl_lightmaps.integer)
8382 t->basetexture = r_texture_grey128;
8383 t->pantstexture = r_texture_black;
8384 t->shirttexture = r_texture_black;
8385 if (gl_lightmaps.integer < 2)
8386 t->nmaptexture = r_texture_blanknormalmap;
8387 t->glosstexture = r_texture_black;
8388 t->glowtexture = NULL;
8389 t->fogtexture = NULL;
8390 t->reflectmasktexture = NULL;
8391 t->backgroundbasetexture = NULL;
8392 if (gl_lightmaps.integer < 2)
8393 t->backgroundnmaptexture = r_texture_blanknormalmap;
8394 t->backgroundglosstexture = r_texture_black;
8395 t->backgroundglowtexture = NULL;
8396 t->specularscale = 0;
8397 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8400 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8401 VectorClear(t->dlightcolor);
8402 t->currentnumlayers = 0;
8403 if (t->currentmaterialflags & MATERIALFLAG_WALL)
8405 int blendfunc1, blendfunc2;
8407 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8409 blendfunc1 = GL_SRC_ALPHA;
8410 blendfunc2 = GL_ONE;
8412 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8414 blendfunc1 = GL_SRC_ALPHA;
8415 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8417 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8419 blendfunc1 = t->customblendfunc[0];
8420 blendfunc2 = t->customblendfunc[1];
8424 blendfunc1 = GL_ONE;
8425 blendfunc2 = GL_ZERO;
8427 // don't colormod evilblend textures
8428 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8429 VectorSet(t->lightmapcolor, 1, 1, 1);
8430 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8431 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8433 // fullbright is not affected by r_refdef.lightmapintensity
8434 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]);
8435 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8436 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
8437 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8438 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * t->lightmapcolor[0], rsurface.colormap_shirtcolor[1] * t->lightmapcolor[1], rsurface.colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
8442 vec3_t ambientcolor;
8444 // set the color tint used for lights affecting this surface
8445 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8447 // q3bsp has no lightmap updates, so the lightstylevalue that
8448 // would normally be baked into the lightmap must be
8449 // applied to the color
8450 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8451 if (model->type == mod_brushq3)
8452 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8453 colorscale *= r_refdef.lightmapintensity;
8454 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8455 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8456 // basic lit geometry
8457 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]);
8458 // add pants/shirt if needed
8459 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8460 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]);
8461 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8462 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]);
8463 // now add ambient passes if needed
8464 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8466 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]);
8467 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8468 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]);
8469 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8470 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]);
8473 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8474 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]);
8475 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8477 // if this is opaque use alpha blend which will darken the earlier
8480 // if this is an alpha blended material, all the earlier passes
8481 // were darkened by fog already, so we only need to add the fog
8482 // color ontop through the fog mask texture
8484 // if this is an additive blended material, all the earlier passes
8485 // were darkened by fog already, and we should not add fog color
8486 // (because the background was not darkened, there is no fog color
8487 // that was lost behind it).
8488 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]);
8495 rsurfacestate_t rsurface;
8497 void RSurf_ActiveWorldEntity(void)
8499 dp_model_t *model = r_refdef.scene.worldmodel;
8500 //if (rsurface.entity == r_refdef.scene.worldentity)
8502 rsurface.entity = r_refdef.scene.worldentity;
8503 rsurface.skeleton = NULL;
8504 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8505 rsurface.ent_skinnum = 0;
8506 rsurface.ent_qwskin = -1;
8507 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8508 rsurface.shadertime = r_refdef.scene.time;
8509 rsurface.matrix = identitymatrix;
8510 rsurface.inversematrix = identitymatrix;
8511 rsurface.matrixscale = 1;
8512 rsurface.inversematrixscale = 1;
8513 R_EntityMatrix(&identitymatrix);
8514 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8515 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8516 rsurface.fograngerecip = r_refdef.fograngerecip;
8517 rsurface.fogheightfade = r_refdef.fogheightfade;
8518 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8519 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8520 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8521 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8522 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8523 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8524 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8525 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8526 rsurface.colormod[3] = 1;
8527 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);
8528 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8529 rsurface.frameblend[0].lerp = 1;
8530 rsurface.ent_alttextures = false;
8531 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8532 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8533 rsurface.entityskeletaltransform3x4 = NULL;
8534 rsurface.entityskeletaltransform3x4buffer = NULL;
8535 rsurface.entityskeletaltransform3x4offset = 0;
8536 rsurface.entityskeletaltransform3x4size = 0;;
8537 rsurface.entityskeletalnumtransforms = 0;
8538 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8539 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8540 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8541 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8542 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8543 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8544 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8545 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8546 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8547 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8548 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8549 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8550 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8551 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8552 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8553 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8554 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8555 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8556 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8557 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8558 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8559 rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8560 rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8561 rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8562 rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8563 rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8564 rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8565 rsurface.modelelement3i = model->surfmesh.data_element3i;
8566 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8567 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8568 rsurface.modelelement3s = model->surfmesh.data_element3s;
8569 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8570 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8571 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8572 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8573 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8574 rsurface.modelsurfaces = model->data_surfaces;
8575 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8576 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8577 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8578 rsurface.modelgeneratedvertex = false;
8579 rsurface.batchgeneratedvertex = false;
8580 rsurface.batchfirstvertex = 0;
8581 rsurface.batchnumvertices = 0;
8582 rsurface.batchfirsttriangle = 0;
8583 rsurface.batchnumtriangles = 0;
8584 rsurface.batchvertex3f = NULL;
8585 rsurface.batchvertex3f_vertexbuffer = NULL;
8586 rsurface.batchvertex3f_bufferoffset = 0;
8587 rsurface.batchsvector3f = NULL;
8588 rsurface.batchsvector3f_vertexbuffer = NULL;
8589 rsurface.batchsvector3f_bufferoffset = 0;
8590 rsurface.batchtvector3f = NULL;
8591 rsurface.batchtvector3f_vertexbuffer = NULL;
8592 rsurface.batchtvector3f_bufferoffset = 0;
8593 rsurface.batchnormal3f = NULL;
8594 rsurface.batchnormal3f_vertexbuffer = NULL;
8595 rsurface.batchnormal3f_bufferoffset = 0;
8596 rsurface.batchlightmapcolor4f = NULL;
8597 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8598 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8599 rsurface.batchtexcoordtexture2f = NULL;
8600 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8601 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8602 rsurface.batchtexcoordlightmap2f = NULL;
8603 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8604 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8605 rsurface.batchskeletalindex4ub = NULL;
8606 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8607 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8608 rsurface.batchskeletalweight4ub = NULL;
8609 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8610 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8611 rsurface.batchvertexmesh = NULL;
8612 rsurface.batchvertexmesh_vertexbuffer = NULL;
8613 rsurface.batchvertexmesh_bufferoffset = 0;
8614 rsurface.batchelement3i = NULL;
8615 rsurface.batchelement3i_indexbuffer = NULL;
8616 rsurface.batchelement3i_bufferoffset = 0;
8617 rsurface.batchelement3s = NULL;
8618 rsurface.batchelement3s_indexbuffer = NULL;
8619 rsurface.batchelement3s_bufferoffset = 0;
8620 rsurface.passcolor4f = NULL;
8621 rsurface.passcolor4f_vertexbuffer = NULL;
8622 rsurface.passcolor4f_bufferoffset = 0;
8623 rsurface.forcecurrenttextureupdate = false;
8626 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8628 dp_model_t *model = ent->model;
8629 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8631 rsurface.entity = (entity_render_t *)ent;
8632 rsurface.skeleton = ent->skeleton;
8633 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8634 rsurface.ent_skinnum = ent->skinnum;
8635 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;
8636 rsurface.ent_flags = ent->flags;
8637 rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8638 rsurface.matrix = ent->matrix;
8639 rsurface.inversematrix = ent->inversematrix;
8640 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8641 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8642 R_EntityMatrix(&rsurface.matrix);
8643 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8644 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8645 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8646 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8647 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8648 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8649 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8650 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8651 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8652 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8653 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8654 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8655 rsurface.colormod[3] = ent->alpha;
8656 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8657 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8658 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8659 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8660 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8661 if (ent->model->brush.submodel && !prepass)
8663 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8664 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8666 // if the animcache code decided it should use the shader path, skip the deform step
8667 rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8668 rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8669 rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8670 rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8671 rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8672 if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8674 if (ent->animcache_vertex3f)
8676 r_refdef.stats[r_stat_batch_entitycache_count]++;
8677 r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8678 r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8679 r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8680 rsurface.modelvertex3f = ent->animcache_vertex3f;
8681 rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8682 rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8683 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8684 rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8685 rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8686 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8687 rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8688 rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8689 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8690 rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8691 rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8692 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8693 rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8694 rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8696 else if (wanttangents)
8698 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8699 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8700 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8701 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8702 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8703 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8704 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8705 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8706 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8707 rsurface.modelvertexmesh = NULL;
8708 rsurface.modelvertexmesh_vertexbuffer = NULL;
8709 rsurface.modelvertexmesh_bufferoffset = 0;
8710 rsurface.modelvertex3f_vertexbuffer = NULL;
8711 rsurface.modelvertex3f_bufferoffset = 0;
8712 rsurface.modelvertex3f_vertexbuffer = 0;
8713 rsurface.modelvertex3f_bufferoffset = 0;
8714 rsurface.modelsvector3f_vertexbuffer = 0;
8715 rsurface.modelsvector3f_bufferoffset = 0;
8716 rsurface.modeltvector3f_vertexbuffer = 0;
8717 rsurface.modeltvector3f_bufferoffset = 0;
8718 rsurface.modelnormal3f_vertexbuffer = 0;
8719 rsurface.modelnormal3f_bufferoffset = 0;
8721 else if (wantnormals)
8723 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8724 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8725 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8726 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8727 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8728 rsurface.modelsvector3f = NULL;
8729 rsurface.modeltvector3f = NULL;
8730 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8731 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8732 rsurface.modelvertexmesh = NULL;
8733 rsurface.modelvertexmesh_vertexbuffer = NULL;
8734 rsurface.modelvertexmesh_bufferoffset = 0;
8735 rsurface.modelvertex3f_vertexbuffer = NULL;
8736 rsurface.modelvertex3f_bufferoffset = 0;
8737 rsurface.modelvertex3f_vertexbuffer = 0;
8738 rsurface.modelvertex3f_bufferoffset = 0;
8739 rsurface.modelsvector3f_vertexbuffer = 0;
8740 rsurface.modelsvector3f_bufferoffset = 0;
8741 rsurface.modeltvector3f_vertexbuffer = 0;
8742 rsurface.modeltvector3f_bufferoffset = 0;
8743 rsurface.modelnormal3f_vertexbuffer = 0;
8744 rsurface.modelnormal3f_bufferoffset = 0;
8748 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8749 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8750 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8751 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8752 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8753 rsurface.modelsvector3f = NULL;
8754 rsurface.modeltvector3f = NULL;
8755 rsurface.modelnormal3f = NULL;
8756 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8757 rsurface.modelvertexmesh = NULL;
8758 rsurface.modelvertexmesh_vertexbuffer = NULL;
8759 rsurface.modelvertexmesh_bufferoffset = 0;
8760 rsurface.modelvertex3f_vertexbuffer = NULL;
8761 rsurface.modelvertex3f_bufferoffset = 0;
8762 rsurface.modelvertex3f_vertexbuffer = 0;
8763 rsurface.modelvertex3f_bufferoffset = 0;
8764 rsurface.modelsvector3f_vertexbuffer = 0;
8765 rsurface.modelsvector3f_bufferoffset = 0;
8766 rsurface.modeltvector3f_vertexbuffer = 0;
8767 rsurface.modeltvector3f_bufferoffset = 0;
8768 rsurface.modelnormal3f_vertexbuffer = 0;
8769 rsurface.modelnormal3f_bufferoffset = 0;
8771 rsurface.modelgeneratedvertex = true;
8775 if (rsurface.entityskeletaltransform3x4)
8777 r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8778 r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8779 r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8780 r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8784 r_refdef.stats[r_stat_batch_entitystatic_count]++;
8785 r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8786 r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8787 r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8789 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8790 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8791 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8792 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8793 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8794 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8795 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8796 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8797 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8798 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8799 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8800 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8801 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8802 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8803 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8804 rsurface.modelgeneratedvertex = false;
8806 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8807 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8808 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8809 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8810 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8811 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8812 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8813 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8814 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8815 rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8816 rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8817 rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8818 rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8819 rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8820 rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8821 rsurface.modelelement3i = model->surfmesh.data_element3i;
8822 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8823 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8824 rsurface.modelelement3s = model->surfmesh.data_element3s;
8825 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8826 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8827 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8828 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8829 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8830 rsurface.modelsurfaces = model->data_surfaces;
8831 rsurface.batchgeneratedvertex = false;
8832 rsurface.batchfirstvertex = 0;
8833 rsurface.batchnumvertices = 0;
8834 rsurface.batchfirsttriangle = 0;
8835 rsurface.batchnumtriangles = 0;
8836 rsurface.batchvertex3f = NULL;
8837 rsurface.batchvertex3f_vertexbuffer = NULL;
8838 rsurface.batchvertex3f_bufferoffset = 0;
8839 rsurface.batchsvector3f = NULL;
8840 rsurface.batchsvector3f_vertexbuffer = NULL;
8841 rsurface.batchsvector3f_bufferoffset = 0;
8842 rsurface.batchtvector3f = NULL;
8843 rsurface.batchtvector3f_vertexbuffer = NULL;
8844 rsurface.batchtvector3f_bufferoffset = 0;
8845 rsurface.batchnormal3f = NULL;
8846 rsurface.batchnormal3f_vertexbuffer = NULL;
8847 rsurface.batchnormal3f_bufferoffset = 0;
8848 rsurface.batchlightmapcolor4f = NULL;
8849 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8850 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8851 rsurface.batchtexcoordtexture2f = NULL;
8852 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8853 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8854 rsurface.batchtexcoordlightmap2f = NULL;
8855 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8856 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8857 rsurface.batchskeletalindex4ub = NULL;
8858 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8859 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8860 rsurface.batchskeletalweight4ub = NULL;
8861 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8862 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8863 rsurface.batchvertexmesh = NULL;
8864 rsurface.batchvertexmesh_vertexbuffer = NULL;
8865 rsurface.batchvertexmesh_bufferoffset = 0;
8866 rsurface.batchelement3i = NULL;
8867 rsurface.batchelement3i_indexbuffer = NULL;
8868 rsurface.batchelement3i_bufferoffset = 0;
8869 rsurface.batchelement3s = NULL;
8870 rsurface.batchelement3s_indexbuffer = NULL;
8871 rsurface.batchelement3s_bufferoffset = 0;
8872 rsurface.passcolor4f = NULL;
8873 rsurface.passcolor4f_vertexbuffer = NULL;
8874 rsurface.passcolor4f_bufferoffset = 0;
8875 rsurface.forcecurrenttextureupdate = false;
8878 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)
8880 rsurface.entity = r_refdef.scene.worldentity;
8881 rsurface.skeleton = NULL;
8882 rsurface.ent_skinnum = 0;
8883 rsurface.ent_qwskin = -1;
8884 rsurface.ent_flags = entflags;
8885 rsurface.shadertime = r_refdef.scene.time - shadertime;
8886 rsurface.modelnumvertices = numvertices;
8887 rsurface.modelnumtriangles = numtriangles;
8888 rsurface.matrix = *matrix;
8889 rsurface.inversematrix = *inversematrix;
8890 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8891 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8892 R_EntityMatrix(&rsurface.matrix);
8893 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8894 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8895 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8896 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8897 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8898 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8899 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8900 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8901 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8902 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8903 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8904 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8905 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);
8906 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8907 rsurface.frameblend[0].lerp = 1;
8908 rsurface.ent_alttextures = false;
8909 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8910 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8911 rsurface.entityskeletaltransform3x4 = NULL;
8912 rsurface.entityskeletaltransform3x4buffer = NULL;
8913 rsurface.entityskeletaltransform3x4offset = 0;
8914 rsurface.entityskeletaltransform3x4size = 0;
8915 rsurface.entityskeletalnumtransforms = 0;
8916 r_refdef.stats[r_stat_batch_entitycustom_count]++;
8917 r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8918 r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8919 r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8922 rsurface.modelvertex3f = (float *)vertex3f;
8923 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8924 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8925 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8927 else if (wantnormals)
8929 rsurface.modelvertex3f = (float *)vertex3f;
8930 rsurface.modelsvector3f = NULL;
8931 rsurface.modeltvector3f = NULL;
8932 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8936 rsurface.modelvertex3f = (float *)vertex3f;
8937 rsurface.modelsvector3f = NULL;
8938 rsurface.modeltvector3f = NULL;
8939 rsurface.modelnormal3f = NULL;
8941 rsurface.modelvertexmesh = NULL;
8942 rsurface.modelvertexmesh_vertexbuffer = NULL;
8943 rsurface.modelvertexmesh_bufferoffset = 0;
8944 rsurface.modelvertex3f_vertexbuffer = 0;
8945 rsurface.modelvertex3f_bufferoffset = 0;
8946 rsurface.modelsvector3f_vertexbuffer = 0;
8947 rsurface.modelsvector3f_bufferoffset = 0;
8948 rsurface.modeltvector3f_vertexbuffer = 0;
8949 rsurface.modeltvector3f_bufferoffset = 0;
8950 rsurface.modelnormal3f_vertexbuffer = 0;
8951 rsurface.modelnormal3f_bufferoffset = 0;
8952 rsurface.modelgeneratedvertex = true;
8953 rsurface.modellightmapcolor4f = (float *)color4f;
8954 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8955 rsurface.modellightmapcolor4f_bufferoffset = 0;
8956 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8957 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8958 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8959 rsurface.modeltexcoordlightmap2f = NULL;
8960 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8961 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8962 rsurface.modelskeletalindex4ub = NULL;
8963 rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8964 rsurface.modelskeletalindex4ub_bufferoffset = 0;
8965 rsurface.modelskeletalweight4ub = NULL;
8966 rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8967 rsurface.modelskeletalweight4ub_bufferoffset = 0;
8968 rsurface.modelelement3i = (int *)element3i;
8969 rsurface.modelelement3i_indexbuffer = NULL;
8970 rsurface.modelelement3i_bufferoffset = 0;
8971 rsurface.modelelement3s = (unsigned short *)element3s;
8972 rsurface.modelelement3s_indexbuffer = NULL;
8973 rsurface.modelelement3s_bufferoffset = 0;
8974 rsurface.modellightmapoffsets = NULL;
8975 rsurface.modelsurfaces = NULL;
8976 rsurface.batchgeneratedvertex = false;
8977 rsurface.batchfirstvertex = 0;
8978 rsurface.batchnumvertices = 0;
8979 rsurface.batchfirsttriangle = 0;
8980 rsurface.batchnumtriangles = 0;
8981 rsurface.batchvertex3f = NULL;
8982 rsurface.batchvertex3f_vertexbuffer = NULL;
8983 rsurface.batchvertex3f_bufferoffset = 0;
8984 rsurface.batchsvector3f = NULL;
8985 rsurface.batchsvector3f_vertexbuffer = NULL;
8986 rsurface.batchsvector3f_bufferoffset = 0;
8987 rsurface.batchtvector3f = NULL;
8988 rsurface.batchtvector3f_vertexbuffer = NULL;
8989 rsurface.batchtvector3f_bufferoffset = 0;
8990 rsurface.batchnormal3f = NULL;
8991 rsurface.batchnormal3f_vertexbuffer = NULL;
8992 rsurface.batchnormal3f_bufferoffset = 0;
8993 rsurface.batchlightmapcolor4f = NULL;
8994 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8995 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8996 rsurface.batchtexcoordtexture2f = NULL;
8997 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8998 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8999 rsurface.batchtexcoordlightmap2f = NULL;
9000 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9001 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9002 rsurface.batchskeletalindex4ub = NULL;
9003 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9004 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9005 rsurface.batchskeletalweight4ub = NULL;
9006 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9007 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9008 rsurface.batchvertexmesh = NULL;
9009 rsurface.batchvertexmesh_vertexbuffer = NULL;
9010 rsurface.batchvertexmesh_bufferoffset = 0;
9011 rsurface.batchelement3i = NULL;
9012 rsurface.batchelement3i_indexbuffer = NULL;
9013 rsurface.batchelement3i_bufferoffset = 0;
9014 rsurface.batchelement3s = NULL;
9015 rsurface.batchelement3s_indexbuffer = NULL;
9016 rsurface.batchelement3s_bufferoffset = 0;
9017 rsurface.passcolor4f = NULL;
9018 rsurface.passcolor4f_vertexbuffer = NULL;
9019 rsurface.passcolor4f_bufferoffset = 0;
9020 rsurface.forcecurrenttextureupdate = true;
9022 if (rsurface.modelnumvertices && rsurface.modelelement3i)
9024 if ((wantnormals || wanttangents) && !normal3f)
9026 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9027 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9029 if (wanttangents && !svector3f)
9031 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9032 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9033 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
9038 float RSurf_FogPoint(const float *v)
9040 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9041 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9042 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9043 float FogHeightFade = r_refdef.fogheightfade;
9045 unsigned int fogmasktableindex;
9046 if (r_refdef.fogplaneviewabove)
9047 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9049 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9050 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9051 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9054 float RSurf_FogVertex(const float *v)
9056 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9057 float FogPlaneViewDist = rsurface.fogplaneviewdist;
9058 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9059 float FogHeightFade = rsurface.fogheightfade;
9061 unsigned int fogmasktableindex;
9062 if (r_refdef.fogplaneviewabove)
9063 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9065 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9066 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9067 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9070 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
9073 for (i = 0;i < numelements;i++)
9074 outelement3i[i] = inelement3i[i] + adjust;
9077 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9078 extern cvar_t gl_vbo;
9079 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9087 int surfacefirsttriangle;
9088 int surfacenumtriangles;
9089 int surfacefirstvertex;
9090 int surfaceendvertex;
9091 int surfacenumvertices;
9092 int batchnumsurfaces = texturenumsurfaces;
9093 int batchnumvertices;
9094 int batchnumtriangles;
9098 qboolean dynamicvertex;
9101 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9104 q3shaderinfo_deform_t *deform;
9105 const msurface_t *surface, *firstsurface;
9106 r_vertexmesh_t *vertexmesh;
9107 if (!texturenumsurfaces)
9109 // find vertex range of this surface batch
9111 firstsurface = texturesurfacelist[0];
9112 firsttriangle = firstsurface->num_firsttriangle;
9113 batchnumvertices = 0;
9114 batchnumtriangles = 0;
9115 firstvertex = endvertex = firstsurface->num_firstvertex;
9116 for (i = 0;i < texturenumsurfaces;i++)
9118 surface = texturesurfacelist[i];
9119 if (surface != firstsurface + i)
9121 surfacefirstvertex = surface->num_firstvertex;
9122 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
9123 surfacenumvertices = surface->num_vertices;
9124 surfacenumtriangles = surface->num_triangles;
9125 if (firstvertex > surfacefirstvertex)
9126 firstvertex = surfacefirstvertex;
9127 if (endvertex < surfaceendvertex)
9128 endvertex = surfaceendvertex;
9129 batchnumvertices += surfacenumvertices;
9130 batchnumtriangles += surfacenumtriangles;
9133 r_refdef.stats[r_stat_batch_batches]++;
9135 r_refdef.stats[r_stat_batch_withgaps]++;
9136 r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
9137 r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
9138 r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
9140 // we now know the vertex range used, and if there are any gaps in it
9141 rsurface.batchfirstvertex = firstvertex;
9142 rsurface.batchnumvertices = endvertex - firstvertex;
9143 rsurface.batchfirsttriangle = firsttriangle;
9144 rsurface.batchnumtriangles = batchnumtriangles;
9146 // this variable holds flags for which properties have been updated that
9147 // may require regenerating vertexmesh array...
9150 // check if any dynamic vertex processing must occur
9151 dynamicvertex = false;
9153 // a cvar to force the dynamic vertex path to be taken, for debugging
9154 if (r_batch_debugdynamicvertexpath.integer)
9158 r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9159 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9160 r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9161 r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9163 dynamicvertex = true;
9166 // if there is a chance of animated vertex colors, it's a dynamic batch
9167 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9171 r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9172 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9173 r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9174 r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9176 dynamicvertex = true;
9177 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9180 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9182 switch (deform->deform)
9185 case Q3DEFORM_PROJECTIONSHADOW:
9186 case Q3DEFORM_TEXT0:
9187 case Q3DEFORM_TEXT1:
9188 case Q3DEFORM_TEXT2:
9189 case Q3DEFORM_TEXT3:
9190 case Q3DEFORM_TEXT4:
9191 case Q3DEFORM_TEXT5:
9192 case Q3DEFORM_TEXT6:
9193 case Q3DEFORM_TEXT7:
9196 case Q3DEFORM_AUTOSPRITE:
9199 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9200 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9201 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9202 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9204 dynamicvertex = true;
9205 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9206 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9208 case Q3DEFORM_AUTOSPRITE2:
9211 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9212 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9213 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9214 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9216 dynamicvertex = true;
9217 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9218 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9220 case Q3DEFORM_NORMAL:
9223 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9224 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9225 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9226 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9228 dynamicvertex = true;
9229 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9230 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9233 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9234 break; // if wavefunc is a nop, ignore this transform
9237 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9238 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9239 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9240 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9242 dynamicvertex = true;
9243 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9244 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9246 case Q3DEFORM_BULGE:
9249 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9250 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9251 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9252 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9254 dynamicvertex = true;
9255 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9256 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9259 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9260 break; // if wavefunc is a nop, ignore this transform
9263 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9264 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9265 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9266 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9268 dynamicvertex = true;
9269 batchneed |= BATCHNEED_ARRAY_VERTEX;
9270 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9274 if (rsurface.texture->materialshaderpass)
9276 switch (rsurface.texture->materialshaderpass->tcgen.tcgen)
9279 case Q3TCGEN_TEXTURE:
9281 case Q3TCGEN_LIGHTMAP:
9284 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9285 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9286 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9287 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9289 dynamicvertex = true;
9290 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9291 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9293 case Q3TCGEN_VECTOR:
9296 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9297 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9298 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9299 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9301 dynamicvertex = true;
9302 batchneed |= BATCHNEED_ARRAY_VERTEX;
9303 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9305 case Q3TCGEN_ENVIRONMENT:
9308 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9309 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9310 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9311 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9313 dynamicvertex = true;
9314 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9315 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9318 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9322 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9323 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9324 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9325 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9327 dynamicvertex = true;
9328 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9329 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9333 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9337 r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9338 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9339 r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9340 r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9342 dynamicvertex = true;
9343 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9346 // when the model data has no vertex buffer (dynamic mesh), we need to
9348 if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9349 batchneed |= BATCHNEED_NOGAPS;
9351 // the caller can specify BATCHNEED_NOGAPS to force a batch with
9352 // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9353 // we ensure this by treating the vertex batch as dynamic...
9354 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9358 r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9359 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9360 r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9361 r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9363 dynamicvertex = true;
9368 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9369 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
9370 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
9371 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
9372 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9373 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9374 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9375 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL) batchneed |= BATCHNEED_ARRAY_SKELETAL;
9378 // if needsupdate, we have to do a dynamic vertex batch for sure
9379 if (needsupdate & batchneed)
9383 r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9384 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9385 r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9386 r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9388 dynamicvertex = true;
9391 // see if we need to build vertexmesh from arrays
9392 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9396 r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9397 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9398 r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9399 r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9401 dynamicvertex = true;
9404 // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9405 if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9406 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9408 rsurface.batchvertex3f = rsurface.modelvertex3f;
9409 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9410 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9411 rsurface.batchsvector3f = rsurface.modelsvector3f;
9412 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9413 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9414 rsurface.batchtvector3f = rsurface.modeltvector3f;
9415 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9416 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9417 rsurface.batchnormal3f = rsurface.modelnormal3f;
9418 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9419 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9420 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9421 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
9422 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
9423 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9424 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
9425 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
9426 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9427 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9428 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9429 rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9430 rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9431 rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9432 rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9433 rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9434 rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9435 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9436 rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9437 rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9438 rsurface.batchelement3i = rsurface.modelelement3i;
9439 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9440 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9441 rsurface.batchelement3s = rsurface.modelelement3s;
9442 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9443 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9444 rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9445 rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9446 rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9447 rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9448 rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9450 // if any dynamic vertex processing has to occur in software, we copy the
9451 // entire surface list together before processing to rebase the vertices
9452 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9454 // if any gaps exist and we do not have a static vertex buffer, we have to
9455 // copy the surface list together to avoid wasting upload bandwidth on the
9456 // vertices in the gaps.
9458 // if gaps exist and we have a static vertex buffer, we can choose whether
9459 // to combine the index buffer ranges into one dynamic index buffer or
9460 // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9462 // in many cases the batch is reduced to one draw call.
9464 rsurface.batchmultidraw = false;
9465 rsurface.batchmultidrawnumsurfaces = 0;
9466 rsurface.batchmultidrawsurfacelist = NULL;
9470 // static vertex data, just set pointers...
9471 rsurface.batchgeneratedvertex = false;
9472 // if there are gaps, we want to build a combined index buffer,
9473 // otherwise use the original static buffer with an appropriate offset
9476 r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9477 r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9478 r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9479 r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9480 if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9482 rsurface.batchmultidraw = true;
9483 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9484 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9487 // build a new triangle elements array for this batch
9488 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9489 rsurface.batchfirsttriangle = 0;
9491 for (i = 0;i < texturenumsurfaces;i++)
9493 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9494 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9495 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9496 numtriangles += surfacenumtriangles;
9498 rsurface.batchelement3i_indexbuffer = NULL;
9499 rsurface.batchelement3i_bufferoffset = 0;
9500 rsurface.batchelement3s = NULL;
9501 rsurface.batchelement3s_indexbuffer = NULL;
9502 rsurface.batchelement3s_bufferoffset = 0;
9503 if (endvertex <= 65536)
9505 // make a 16bit (unsigned short) index array if possible
9506 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9507 for (i = 0;i < numtriangles*3;i++)
9508 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9510 // upload buffer data for the copytriangles batch
9511 if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9513 if (rsurface.batchelement3s)
9514 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9515 else if (rsurface.batchelement3i)
9516 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9521 r_refdef.stats[r_stat_batch_fast_batches] += 1;
9522 r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9523 r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9524 r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9529 // something needs software processing, do it for real...
9530 // we only directly handle separate array data in this case and then
9531 // generate interleaved data if needed...
9532 rsurface.batchgeneratedvertex = true;
9533 r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9534 r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9535 r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9536 r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9538 // now copy the vertex data into a combined array and make an index array
9539 // (this is what Quake3 does all the time)
9540 // we also apply any skeletal animation here that would have been done in
9541 // the vertex shader, because most of the dynamic vertex animation cases
9542 // need actual vertex positions and normals
9543 //if (dynamicvertex)
9545 rsurface.batchvertexmesh = NULL;
9546 rsurface.batchvertexmesh_vertexbuffer = NULL;
9547 rsurface.batchvertexmesh_bufferoffset = 0;
9548 rsurface.batchvertex3f = NULL;
9549 rsurface.batchvertex3f_vertexbuffer = NULL;
9550 rsurface.batchvertex3f_bufferoffset = 0;
9551 rsurface.batchsvector3f = NULL;
9552 rsurface.batchsvector3f_vertexbuffer = NULL;
9553 rsurface.batchsvector3f_bufferoffset = 0;
9554 rsurface.batchtvector3f = NULL;
9555 rsurface.batchtvector3f_vertexbuffer = NULL;
9556 rsurface.batchtvector3f_bufferoffset = 0;
9557 rsurface.batchnormal3f = NULL;
9558 rsurface.batchnormal3f_vertexbuffer = NULL;
9559 rsurface.batchnormal3f_bufferoffset = 0;
9560 rsurface.batchlightmapcolor4f = NULL;
9561 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9562 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9563 rsurface.batchtexcoordtexture2f = NULL;
9564 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9565 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9566 rsurface.batchtexcoordlightmap2f = NULL;
9567 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9568 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9569 rsurface.batchskeletalindex4ub = NULL;
9570 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9571 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9572 rsurface.batchskeletalweight4ub = NULL;
9573 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9574 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9575 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9576 rsurface.batchelement3i_indexbuffer = NULL;
9577 rsurface.batchelement3i_bufferoffset = 0;
9578 rsurface.batchelement3s = NULL;
9579 rsurface.batchelement3s_indexbuffer = NULL;
9580 rsurface.batchelement3s_bufferoffset = 0;
9581 rsurface.batchskeletaltransform3x4buffer = NULL;
9582 rsurface.batchskeletaltransform3x4offset = 0;
9583 rsurface.batchskeletaltransform3x4size = 0;
9584 // we'll only be setting up certain arrays as needed
9585 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9586 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9587 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9588 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9589 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9590 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9591 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9593 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9594 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9596 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9597 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9598 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9599 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9600 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9601 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9602 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9604 rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9605 rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9609 for (i = 0;i < texturenumsurfaces;i++)
9611 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9612 surfacenumvertices = texturesurfacelist[i]->num_vertices;
9613 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9614 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9615 // copy only the data requested
9616 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9617 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9618 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9620 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9622 if (rsurface.batchvertex3f)
9623 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9625 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9627 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9629 if (rsurface.modelnormal3f)
9630 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9632 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9634 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9636 if (rsurface.modelsvector3f)
9638 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9639 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9643 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9644 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9647 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9649 if (rsurface.modellightmapcolor4f)
9650 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9652 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9654 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9656 if (rsurface.modeltexcoordtexture2f)
9657 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9659 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9661 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9663 if (rsurface.modeltexcoordlightmap2f)
9664 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9666 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9668 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9670 if (rsurface.modelskeletalindex4ub)
9672 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9673 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9677 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9678 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9679 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9680 for (j = 0;j < surfacenumvertices;j++)
9685 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9686 numvertices += surfacenumvertices;
9687 numtriangles += surfacenumtriangles;
9690 // generate a 16bit index array as well if possible
9691 // (in general, dynamic batches fit)
9692 if (numvertices <= 65536)
9694 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9695 for (i = 0;i < numtriangles*3;i++)
9696 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9699 // since we've copied everything, the batch now starts at 0
9700 rsurface.batchfirstvertex = 0;
9701 rsurface.batchnumvertices = batchnumvertices;
9702 rsurface.batchfirsttriangle = 0;
9703 rsurface.batchnumtriangles = batchnumtriangles;
9706 // apply skeletal animation that would have been done in the vertex shader
9707 if (rsurface.batchskeletaltransform3x4)
9709 const unsigned char *si;
9710 const unsigned char *sw;
9712 const float *b = rsurface.batchskeletaltransform3x4;
9713 float *vp, *vs, *vt, *vn;
9715 float m[3][4], n[3][4];
9716 float tp[3], ts[3], tt[3], tn[3];
9717 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9718 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9719 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9720 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9721 si = rsurface.batchskeletalindex4ub;
9722 sw = rsurface.batchskeletalweight4ub;
9723 vp = rsurface.batchvertex3f;
9724 vs = rsurface.batchsvector3f;
9725 vt = rsurface.batchtvector3f;
9726 vn = rsurface.batchnormal3f;
9727 memset(m[0], 0, sizeof(m));
9728 memset(n[0], 0, sizeof(n));
9729 for (i = 0;i < batchnumvertices;i++)
9731 t[0] = b + si[0]*12;
9734 // common case - only one matrix
9748 else if (sw[2] + sw[3])
9751 t[1] = b + si[1]*12;
9752 t[2] = b + si[2]*12;
9753 t[3] = b + si[3]*12;
9754 w[0] = sw[0] * (1.0f / 255.0f);
9755 w[1] = sw[1] * (1.0f / 255.0f);
9756 w[2] = sw[2] * (1.0f / 255.0f);
9757 w[3] = sw[3] * (1.0f / 255.0f);
9758 // blend the matrices
9759 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9760 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9761 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9762 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9763 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9764 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9765 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9766 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9767 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9768 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9769 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9770 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9775 t[1] = b + si[1]*12;
9776 w[0] = sw[0] * (1.0f / 255.0f);
9777 w[1] = sw[1] * (1.0f / 255.0f);
9778 // blend the matrices
9779 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9780 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9781 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9782 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9783 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9784 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9785 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9786 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9787 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9788 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9789 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9790 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9794 // modify the vertex
9796 vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9797 vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9798 vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9802 // the normal transformation matrix is a set of cross products...
9803 CrossProduct(m[1], m[2], n[0]);
9804 CrossProduct(m[2], m[0], n[1]);
9805 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9807 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9808 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9809 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9810 VectorNormalize(vn);
9815 vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9816 vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9817 vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9818 VectorNormalize(vs);
9821 vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9822 vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9823 vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9824 VectorNormalize(vt);
9829 rsurface.batchskeletaltransform3x4 = NULL;
9830 rsurface.batchskeletalnumtransforms = 0;
9833 // q1bsp surfaces rendered in vertex color mode have to have colors
9834 // calculated based on lightstyles
9835 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9837 // generate color arrays for the surfaces in this list
9842 const unsigned char *lm;
9843 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9844 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9845 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9847 for (i = 0;i < texturenumsurfaces;i++)
9849 surface = texturesurfacelist[i];
9850 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9851 surfacenumvertices = surface->num_vertices;
9852 if (surface->lightmapinfo->samples)
9854 for (j = 0;j < surfacenumvertices;j++)
9856 lm = surface->lightmapinfo->samples + offsets[j];
9857 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9858 VectorScale(lm, scale, c);
9859 if (surface->lightmapinfo->styles[1] != 255)
9861 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9863 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9864 VectorMA(c, scale, lm, c);
9865 if (surface->lightmapinfo->styles[2] != 255)
9868 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9869 VectorMA(c, scale, lm, c);
9870 if (surface->lightmapinfo->styles[3] != 255)
9873 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9874 VectorMA(c, scale, lm, c);
9881 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);
9887 for (j = 0;j < surfacenumvertices;j++)
9889 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9896 // if vertices are deformed (sprite flares and things in maps, possibly
9897 // water waves, bulges and other deformations), modify the copied vertices
9899 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9902 switch (deform->deform)
9905 case Q3DEFORM_PROJECTIONSHADOW:
9906 case Q3DEFORM_TEXT0:
9907 case Q3DEFORM_TEXT1:
9908 case Q3DEFORM_TEXT2:
9909 case Q3DEFORM_TEXT3:
9910 case Q3DEFORM_TEXT4:
9911 case Q3DEFORM_TEXT5:
9912 case Q3DEFORM_TEXT6:
9913 case Q3DEFORM_TEXT7:
9916 case Q3DEFORM_AUTOSPRITE:
9917 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9918 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9919 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9920 VectorNormalize(newforward);
9921 VectorNormalize(newright);
9922 VectorNormalize(newup);
9923 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9924 // rsurface.batchvertex3f_vertexbuffer = NULL;
9925 // rsurface.batchvertex3f_bufferoffset = 0;
9926 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9927 // rsurface.batchsvector3f_vertexbuffer = NULL;
9928 // rsurface.batchsvector3f_bufferoffset = 0;
9929 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9930 // rsurface.batchtvector3f_vertexbuffer = NULL;
9931 // rsurface.batchtvector3f_bufferoffset = 0;
9932 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9933 // rsurface.batchnormal3f_vertexbuffer = NULL;
9934 // rsurface.batchnormal3f_bufferoffset = 0;
9935 // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9936 if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9937 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9938 if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9939 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);
9940 // a single autosprite surface can contain multiple sprites...
9941 for (j = 0;j < batchnumvertices - 3;j += 4)
9943 VectorClear(center);
9944 for (i = 0;i < 4;i++)
9945 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9946 VectorScale(center, 0.25f, center);
9947 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9948 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9949 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9950 for (i = 0;i < 4;i++)
9952 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9953 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9956 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9957 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9958 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);
9960 case Q3DEFORM_AUTOSPRITE2:
9961 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9962 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9963 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9964 VectorNormalize(newforward);
9965 VectorNormalize(newright);
9966 VectorNormalize(newup);
9967 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9968 // rsurface.batchvertex3f_vertexbuffer = NULL;
9969 // rsurface.batchvertex3f_bufferoffset = 0;
9971 const float *v1, *v2;
9981 memset(shortest, 0, sizeof(shortest));
9982 // a single autosprite surface can contain multiple sprites...
9983 for (j = 0;j < batchnumvertices - 3;j += 4)
9985 VectorClear(center);
9986 for (i = 0;i < 4;i++)
9987 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9988 VectorScale(center, 0.25f, center);
9989 // find the two shortest edges, then use them to define the
9990 // axis vectors for rotating around the central axis
9991 for (i = 0;i < 6;i++)
9993 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9994 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9995 l = VectorDistance2(v1, v2);
9996 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9998 l += (1.0f / 1024.0f);
9999 if (shortest[0].length2 > l || i == 0)
10001 shortest[1] = shortest[0];
10002 shortest[0].length2 = l;
10003 shortest[0].v1 = v1;
10004 shortest[0].v2 = v2;
10006 else if (shortest[1].length2 > l || i == 1)
10008 shortest[1].length2 = l;
10009 shortest[1].v1 = v1;
10010 shortest[1].v2 = v2;
10013 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
10014 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
10015 // this calculates the right vector from the shortest edge
10016 // and the up vector from the edge midpoints
10017 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
10018 VectorNormalize(right);
10019 VectorSubtract(end, start, up);
10020 VectorNormalize(up);
10021 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
10022 VectorSubtract(rsurface.localvieworigin, center, forward);
10023 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
10024 VectorNegate(forward, forward);
10025 VectorReflect(forward, 0, up, forward);
10026 VectorNormalize(forward);
10027 CrossProduct(up, forward, newright);
10028 VectorNormalize(newright);
10029 // rotate the quad around the up axis vector, this is made
10030 // especially easy by the fact we know the quad is flat,
10031 // so we only have to subtract the center position and
10032 // measure distance along the right vector, and then
10033 // multiply that by the newright vector and add back the
10035 // we also need to subtract the old position to undo the
10036 // displacement from the center, which we do with a
10037 // DotProduct, the subtraction/addition of center is also
10038 // optimized into DotProducts here
10039 l = DotProduct(right, center);
10040 for (i = 0;i < 4;i++)
10042 v1 = rsurface.batchvertex3f + 3*(j+i);
10043 f = DotProduct(right, v1) - l;
10044 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
10048 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
10050 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10051 // rsurface.batchnormal3f_vertexbuffer = NULL;
10052 // rsurface.batchnormal3f_bufferoffset = 0;
10053 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10055 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10057 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10058 // rsurface.batchsvector3f_vertexbuffer = NULL;
10059 // rsurface.batchsvector3f_bufferoffset = 0;
10060 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10061 // rsurface.batchtvector3f_vertexbuffer = NULL;
10062 // rsurface.batchtvector3f_bufferoffset = 0;
10063 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);
10066 case Q3DEFORM_NORMAL:
10067 // deform the normals to make reflections wavey
10068 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10069 rsurface.batchnormal3f_vertexbuffer = NULL;
10070 rsurface.batchnormal3f_bufferoffset = 0;
10071 for (j = 0;j < batchnumvertices;j++)
10074 float *normal = rsurface.batchnormal3f + 3*j;
10075 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
10076 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10077 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10078 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10079 VectorNormalize(normal);
10081 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10083 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10084 // rsurface.batchsvector3f_vertexbuffer = NULL;
10085 // rsurface.batchsvector3f_bufferoffset = 0;
10086 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10087 // rsurface.batchtvector3f_vertexbuffer = NULL;
10088 // rsurface.batchtvector3f_bufferoffset = 0;
10089 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);
10092 case Q3DEFORM_WAVE:
10093 // deform vertex array to make wavey water and flags and such
10094 waveparms[0] = deform->waveparms[0];
10095 waveparms[1] = deform->waveparms[1];
10096 waveparms[2] = deform->waveparms[2];
10097 waveparms[3] = deform->waveparms[3];
10098 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
10099 break; // if wavefunc is a nop, don't make a dynamic vertex array
10100 // this is how a divisor of vertex influence on deformation
10101 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10102 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
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 // if the wavefunc depends on time, evaluate it per-vertex
10114 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
10115 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10117 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10119 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10120 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10121 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10123 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10124 // rsurface.batchsvector3f_vertexbuffer = NULL;
10125 // rsurface.batchsvector3f_bufferoffset = 0;
10126 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10127 // rsurface.batchtvector3f_vertexbuffer = NULL;
10128 // rsurface.batchtvector3f_bufferoffset = 0;
10129 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);
10132 case Q3DEFORM_BULGE:
10133 // deform vertex array to make the surface have moving bulges
10134 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10135 // rsurface.batchvertex3f_vertexbuffer = NULL;
10136 // rsurface.batchvertex3f_bufferoffset = 0;
10137 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10138 // rsurface.batchnormal3f_vertexbuffer = NULL;
10139 // rsurface.batchnormal3f_bufferoffset = 0;
10140 for (j = 0;j < batchnumvertices;j++)
10142 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
10143 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10145 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10146 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10147 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10149 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10150 // rsurface.batchsvector3f_vertexbuffer = NULL;
10151 // rsurface.batchsvector3f_bufferoffset = 0;
10152 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10153 // rsurface.batchtvector3f_vertexbuffer = NULL;
10154 // rsurface.batchtvector3f_bufferoffset = 0;
10155 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);
10158 case Q3DEFORM_MOVE:
10159 // deform vertex array
10160 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10161 break; // if wavefunc is a nop, don't make a dynamic vertex array
10162 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10163 VectorScale(deform->parms, scale, waveparms);
10164 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10165 // rsurface.batchvertex3f_vertexbuffer = NULL;
10166 // rsurface.batchvertex3f_bufferoffset = 0;
10167 for (j = 0;j < batchnumvertices;j++)
10168 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10173 if (rsurface.batchtexcoordtexture2f && rsurface.texture->materialshaderpass)
10175 // generate texcoords based on the chosen texcoord source
10176 switch(rsurface.texture->materialshaderpass->tcgen.tcgen)
10179 case Q3TCGEN_TEXTURE:
10181 case Q3TCGEN_LIGHTMAP:
10182 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10183 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10184 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10185 if (rsurface.batchtexcoordlightmap2f)
10186 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
10188 case Q3TCGEN_VECTOR:
10189 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10190 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10191 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10192 for (j = 0;j < batchnumvertices;j++)
10194 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms);
10195 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms + 3);
10198 case Q3TCGEN_ENVIRONMENT:
10199 // make environment reflections using a spheremap
10200 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10201 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10202 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10203 for (j = 0;j < batchnumvertices;j++)
10205 // identical to Q3A's method, but executed in worldspace so
10206 // carried models can be shiny too
10208 float viewer[3], d, reflected[3], worldreflected[3];
10210 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10211 // VectorNormalize(viewer);
10213 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10215 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10216 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10217 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10218 // note: this is proportinal to viewer, so we can normalize later
10220 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10221 VectorNormalize(worldreflected);
10223 // note: this sphere map only uses world x and z!
10224 // so positive and negative y will LOOK THE SAME.
10225 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10226 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10230 // the only tcmod that needs software vertex processing is turbulent, so
10231 // check for it here and apply the changes if needed
10232 // and we only support that as the first one
10233 // (handling a mixture of turbulent and other tcmods would be problematic
10234 // without punting it entirely to a software path)
10235 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10237 amplitude = rsurface.texture->materialshaderpass->tcmods[0].parms[1];
10238 animpos = rsurface.texture->materialshaderpass->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->materialshaderpass->tcmods[0].parms[3];
10239 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10240 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10241 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10242 for (j = 0;j < batchnumvertices;j++)
10244 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);
10245 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10250 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10252 // convert the modified arrays to vertex structs
10253 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10254 // rsurface.batchvertexmesh_vertexbuffer = NULL;
10255 // rsurface.batchvertexmesh_bufferoffset = 0;
10256 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10257 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10258 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10259 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10260 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10261 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10262 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10264 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10266 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10267 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10270 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10271 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10272 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10273 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10274 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10275 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10276 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10277 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10278 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10279 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10281 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10283 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10284 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10289 // upload buffer data for the dynamic batch
10290 if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10292 if (rsurface.batchvertexmesh)
10293 rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10296 if (rsurface.batchvertex3f)
10297 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10298 if (rsurface.batchsvector3f)
10299 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10300 if (rsurface.batchtvector3f)
10301 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10302 if (rsurface.batchnormal3f)
10303 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10304 if (rsurface.batchlightmapcolor4f)
10305 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10306 if (rsurface.batchtexcoordtexture2f)
10307 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10308 if (rsurface.batchtexcoordlightmap2f)
10309 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10310 if (rsurface.batchskeletalindex4ub)
10311 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10312 if (rsurface.batchskeletalweight4ub)
10313 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10315 if (rsurface.batchelement3s)
10316 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10317 else if (rsurface.batchelement3i)
10318 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10322 void RSurf_DrawBatch(void)
10324 // sometimes a zero triangle surface (usually a degenerate patch) makes it
10325 // through the pipeline, killing it earlier in the pipeline would have
10326 // per-surface overhead rather than per-batch overhead, so it's best to
10327 // reject it here, before it hits glDraw.
10328 if (rsurface.batchnumtriangles == 0)
10331 // batch debugging code
10332 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10338 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10339 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10342 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10344 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10346 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10347 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);
10354 if (rsurface.batchmultidraw)
10356 // issue multiple draws rather than copying index data
10357 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10358 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10359 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10360 for (i = 0;i < numsurfaces;)
10362 // combine consecutive surfaces as one draw
10363 for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10364 if (surfacelist[j] != surfacelist[k] + 1)
10366 firstvertex = surfacelist[i]->num_firstvertex;
10367 endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10368 firsttriangle = surfacelist[i]->num_firsttriangle;
10369 endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10370 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);
10376 // there is only one consecutive run of index data (may have been combined)
10377 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);
10381 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10383 // pick the closest matching water plane
10384 int planeindex, vertexindex, bestplaneindex = -1;
10388 r_waterstate_waterplane_t *p;
10389 qboolean prepared = false;
10391 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10393 if(p->camera_entity != rsurface.texture->camera_entity)
10398 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10400 if(rsurface.batchnumvertices == 0)
10403 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10405 Matrix4x4_Transform(&rsurface.matrix, v, vert);
10406 d += fabs(PlaneDiff(vert, &p->plane));
10408 if (bestd > d || bestplaneindex < 0)
10411 bestplaneindex = planeindex;
10414 return bestplaneindex;
10415 // NOTE: this MAY return a totally unrelated water plane; we can ignore
10416 // this situation though, as it might be better to render single larger
10417 // batches with useless stuff (backface culled for example) than to
10418 // render multiple smaller batches
10421 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10424 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10425 rsurface.passcolor4f_vertexbuffer = 0;
10426 rsurface.passcolor4f_bufferoffset = 0;
10427 for (i = 0;i < rsurface.batchnumvertices;i++)
10428 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10431 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10438 if (rsurface.passcolor4f)
10440 // generate color arrays
10441 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10442 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10443 rsurface.passcolor4f_vertexbuffer = 0;
10444 rsurface.passcolor4f_bufferoffset = 0;
10445 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)
10447 f = RSurf_FogVertex(v);
10456 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10457 rsurface.passcolor4f_vertexbuffer = 0;
10458 rsurface.passcolor4f_bufferoffset = 0;
10459 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10461 f = RSurf_FogVertex(v);
10470 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10477 if (!rsurface.passcolor4f)
10479 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10480 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10481 rsurface.passcolor4f_vertexbuffer = 0;
10482 rsurface.passcolor4f_bufferoffset = 0;
10483 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)
10485 f = RSurf_FogVertex(v);
10486 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10487 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10488 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10493 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10498 if (!rsurface.passcolor4f)
10500 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10501 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10502 rsurface.passcolor4f_vertexbuffer = 0;
10503 rsurface.passcolor4f_bufferoffset = 0;
10504 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10513 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10518 if (!rsurface.passcolor4f)
10520 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10521 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10522 rsurface.passcolor4f_vertexbuffer = 0;
10523 rsurface.passcolor4f_bufferoffset = 0;
10524 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10526 c2[0] = c[0] + r_refdef.scene.ambient;
10527 c2[1] = c[1] + r_refdef.scene.ambient;
10528 c2[2] = c[2] + r_refdef.scene.ambient;
10533 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10536 rsurface.passcolor4f = NULL;
10537 rsurface.passcolor4f_vertexbuffer = 0;
10538 rsurface.passcolor4f_bufferoffset = 0;
10539 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10540 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10541 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10542 GL_Color(r, g, b, a);
10543 R_Mesh_TexBind(0, rsurface.lightmaptexture);
10544 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10545 R_Mesh_TexMatrix(0, NULL);
10549 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10551 // TODO: optimize applyfog && applycolor case
10552 // just apply fog if necessary, and tint the fog color array if necessary
10553 rsurface.passcolor4f = NULL;
10554 rsurface.passcolor4f_vertexbuffer = 0;
10555 rsurface.passcolor4f_bufferoffset = 0;
10556 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10557 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10558 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10559 GL_Color(r, g, b, a);
10563 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10566 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10567 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10568 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10569 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10570 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10571 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10572 GL_Color(r, g, b, a);
10576 static void RSurf_DrawBatch_GL11_ClampColor(void)
10581 if (!rsurface.passcolor4f)
10583 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10585 c2[0] = bound(0.0f, c1[0], 1.0f);
10586 c2[1] = bound(0.0f, c1[1], 1.0f);
10587 c2[2] = bound(0.0f, c1[2], 1.0f);
10588 c2[3] = bound(0.0f, c1[3], 1.0f);
10592 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10602 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10603 rsurface.passcolor4f_vertexbuffer = 0;
10604 rsurface.passcolor4f_bufferoffset = 0;
10605 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)
10607 f = -DotProduct(r_refdef.view.forward, n);
10609 f = f * 0.85 + 0.15; // work around so stuff won't get black
10610 f *= r_refdef.lightmapintensity;
10611 Vector4Set(c, f, f, f, 1);
10615 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10617 RSurf_DrawBatch_GL11_ApplyFakeLight();
10618 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10619 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10620 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10621 GL_Color(r, g, b, a);
10625 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10633 vec3_t ambientcolor;
10634 vec3_t diffusecolor;
10638 VectorCopy(rsurface.modellight_lightdir, lightdir);
10639 f = 0.5f * r_refdef.lightmapintensity;
10640 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10641 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10642 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10643 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10644 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10645 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10647 if (VectorLength2(diffusecolor) > 0)
10649 // q3-style directional shading
10650 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10651 rsurface.passcolor4f_vertexbuffer = 0;
10652 rsurface.passcolor4f_bufferoffset = 0;
10653 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)
10655 if ((f = DotProduct(n, lightdir)) > 0)
10656 VectorMA(ambientcolor, f, diffusecolor, c);
10658 VectorCopy(ambientcolor, c);
10665 *applycolor = false;
10669 *r = ambientcolor[0];
10670 *g = ambientcolor[1];
10671 *b = ambientcolor[2];
10672 rsurface.passcolor4f = NULL;
10673 rsurface.passcolor4f_vertexbuffer = 0;
10674 rsurface.passcolor4f_bufferoffset = 0;
10678 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10680 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10681 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10682 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10683 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10684 GL_Color(r, g, b, a);
10688 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10696 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10697 rsurface.passcolor4f_vertexbuffer = 0;
10698 rsurface.passcolor4f_bufferoffset = 0;
10700 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10702 f = 1 - RSurf_FogVertex(v);
10710 void RSurf_SetupDepthAndCulling(void)
10712 // submodels are biased to avoid z-fighting with world surfaces that they
10713 // may be exactly overlapping (avoids z-fighting artifacts on certain
10714 // doors and things in Quake maps)
10715 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10716 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10717 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10718 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10721 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10723 // transparent sky would be ridiculous
10724 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10726 R_SetupShader_Generic_NoTexture(false, false);
10727 skyrenderlater = true;
10728 RSurf_SetupDepthAndCulling();
10729 GL_DepthMask(true);
10730 // LordHavoc: HalfLife maps have freaky skypolys so don't use
10731 // skymasking on them, and Quake3 never did sky masking (unlike
10732 // software Quake and software Quake2), so disable the sky masking
10733 // in Quake3 maps as it causes problems with q3map2 sky tricks,
10734 // and skymasking also looks very bad when noclipping outside the
10735 // level, so don't use it then either.
10736 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.skymasking && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10738 R_Mesh_ResetTextureState();
10739 if (skyrendermasked)
10741 R_SetupShader_DepthOrShadow(false, false, false);
10742 // depth-only (masking)
10743 GL_ColorMask(0,0,0,0);
10744 // just to make sure that braindead drivers don't draw
10745 // anything despite that colormask...
10746 GL_BlendFunc(GL_ZERO, GL_ONE);
10747 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10748 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10752 R_SetupShader_Generic_NoTexture(false, false);
10754 GL_BlendFunc(GL_ONE, GL_ZERO);
10755 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10756 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10757 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10760 if (skyrendermasked)
10761 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10763 R_Mesh_ResetTextureState();
10764 GL_Color(1, 1, 1, 1);
10767 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10768 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10769 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10771 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10775 // render screenspace normalmap to texture
10776 GL_DepthMask(true);
10777 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10782 // bind lightmap texture
10784 // water/refraction/reflection/camera surfaces have to be handled specially
10785 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10787 int start, end, startplaneindex;
10788 for (start = 0;start < texturenumsurfaces;start = end)
10790 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10791 if(startplaneindex < 0)
10793 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10794 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10798 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10800 // now that we have a batch using the same planeindex, render it
10801 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10803 // render water or distortion background
10804 GL_DepthMask(true);
10805 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);
10807 // blend surface on top
10808 GL_DepthMask(false);
10809 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10812 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10814 // render surface with reflection texture as input
10815 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10816 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);
10823 // render surface batch normally
10824 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10825 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);
10829 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10831 // OpenGL 1.3 path - anything not completely ancient
10832 qboolean applycolor;
10835 const texturelayer_t *layer;
10836 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);
10837 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10839 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10842 int layertexrgbscale;
10843 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10845 if (layerindex == 0)
10846 GL_AlphaTest(true);
10849 GL_AlphaTest(false);
10850 GL_DepthFunc(GL_EQUAL);
10853 GL_DepthMask(layer->depthmask && writedepth);
10854 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10855 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10857 layertexrgbscale = 4;
10858 VectorScale(layer->color, 0.25f, layercolor);
10860 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10862 layertexrgbscale = 2;
10863 VectorScale(layer->color, 0.5f, layercolor);
10867 layertexrgbscale = 1;
10868 VectorScale(layer->color, 1.0f, layercolor);
10870 layercolor[3] = layer->color[3];
10871 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10872 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10873 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10874 switch (layer->type)
10876 case TEXTURELAYERTYPE_LITTEXTURE:
10877 // single-pass lightmapped texture with 2x rgbscale
10878 R_Mesh_TexBind(0, r_texture_white);
10879 R_Mesh_TexMatrix(0, NULL);
10880 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10881 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10882 R_Mesh_TexBind(1, layer->texture);
10883 R_Mesh_TexMatrix(1, &layer->texmatrix);
10884 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10885 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10886 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10887 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10888 else if (FAKELIGHT_ENABLED)
10889 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10890 else if (rsurface.uselightmaptexture)
10891 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10893 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10895 case TEXTURELAYERTYPE_TEXTURE:
10896 // singletexture unlit texture with transparency support
10897 R_Mesh_TexBind(0, layer->texture);
10898 R_Mesh_TexMatrix(0, &layer->texmatrix);
10899 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10900 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10901 R_Mesh_TexBind(1, 0);
10902 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10903 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10905 case TEXTURELAYERTYPE_FOG:
10906 // singletexture fogging
10907 if (layer->texture)
10909 R_Mesh_TexBind(0, layer->texture);
10910 R_Mesh_TexMatrix(0, &layer->texmatrix);
10911 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10912 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10916 R_Mesh_TexBind(0, 0);
10917 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10919 R_Mesh_TexBind(1, 0);
10920 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10921 // generate a color array for the fog pass
10922 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10923 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10927 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10930 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10932 GL_DepthFunc(GL_LEQUAL);
10933 GL_AlphaTest(false);
10937 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10939 // OpenGL 1.1 - crusty old voodoo path
10942 const texturelayer_t *layer;
10943 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);
10944 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10946 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10948 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10950 if (layerindex == 0)
10951 GL_AlphaTest(true);
10954 GL_AlphaTest(false);
10955 GL_DepthFunc(GL_EQUAL);
10958 GL_DepthMask(layer->depthmask && writedepth);
10959 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10960 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10961 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10962 switch (layer->type)
10964 case TEXTURELAYERTYPE_LITTEXTURE:
10965 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10967 // two-pass lit texture with 2x rgbscale
10968 // first the lightmap pass
10969 R_Mesh_TexBind(0, r_texture_white);
10970 R_Mesh_TexMatrix(0, NULL);
10971 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10972 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10973 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10974 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10975 else if (FAKELIGHT_ENABLED)
10976 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10977 else if (rsurface.uselightmaptexture)
10978 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10980 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10981 // then apply the texture to it
10982 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10983 R_Mesh_TexBind(0, layer->texture);
10984 R_Mesh_TexMatrix(0, &layer->texmatrix);
10985 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10986 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10987 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);
10991 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10992 R_Mesh_TexBind(0, layer->texture);
10993 R_Mesh_TexMatrix(0, &layer->texmatrix);
10994 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10995 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10996 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10997 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);
10998 else if (FAKELIGHT_ENABLED)
10999 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);
11001 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);
11004 case TEXTURELAYERTYPE_TEXTURE:
11005 // singletexture unlit texture with transparency support
11006 R_Mesh_TexBind(0, layer->texture);
11007 R_Mesh_TexMatrix(0, &layer->texmatrix);
11008 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11009 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11010 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);
11012 case TEXTURELAYERTYPE_FOG:
11013 // singletexture fogging
11014 if (layer->texture)
11016 R_Mesh_TexBind(0, layer->texture);
11017 R_Mesh_TexMatrix(0, &layer->texmatrix);
11018 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11019 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11023 R_Mesh_TexBind(0, 0);
11024 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
11026 // generate a color array for the fog pass
11027 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
11028 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
11032 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11035 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11037 GL_DepthFunc(GL_LEQUAL);
11038 GL_AlphaTest(false);
11042 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11046 r_vertexgeneric_t *batchvertex;
11049 // R_Mesh_ResetTextureState();
11050 R_SetupShader_Generic_NoTexture(false, false);
11052 if(rsurface.texture && rsurface.texture->currentskinframe)
11054 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
11055 c[3] *= rsurface.texture->currentalpha;
11065 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
11067 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
11068 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
11069 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
11072 // brighten it up (as texture value 127 means "unlit")
11073 c[0] *= 2 * r_refdef.view.colorscale;
11074 c[1] *= 2 * r_refdef.view.colorscale;
11075 c[2] *= 2 * r_refdef.view.colorscale;
11077 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11078 c[3] *= r_wateralpha.value;
11080 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11082 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11083 GL_DepthMask(false);
11085 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11087 GL_BlendFunc(GL_ONE, GL_ONE);
11088 GL_DepthMask(false);
11090 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11092 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11093 GL_DepthMask(false);
11095 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11097 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11098 GL_DepthMask(false);
11102 GL_BlendFunc(GL_ONE, GL_ZERO);
11103 GL_DepthMask(writedepth);
11106 if (r_showsurfaces.integer == 3)
11108 rsurface.passcolor4f = NULL;
11110 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11112 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11114 rsurface.passcolor4f = NULL;
11115 rsurface.passcolor4f_vertexbuffer = 0;
11116 rsurface.passcolor4f_bufferoffset = 0;
11118 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11120 qboolean applycolor = true;
11123 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11125 r_refdef.lightmapintensity = 1;
11126 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
11127 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11129 else if (FAKELIGHT_ENABLED)
11131 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11133 r_refdef.lightmapintensity = r_fakelight_intensity.value;
11134 RSurf_DrawBatch_GL11_ApplyFakeLight();
11135 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11139 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11141 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11142 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11143 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11146 if(!rsurface.passcolor4f)
11147 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11149 RSurf_DrawBatch_GL11_ApplyAmbient();
11150 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11151 if(r_refdef.fogenabled)
11152 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11153 RSurf_DrawBatch_GL11_ClampColor();
11155 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11156 R_SetupShader_Generic_NoTexture(false, false);
11159 else if (!r_refdef.view.showdebug)
11161 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11162 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11163 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11165 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11166 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11168 R_Mesh_PrepareVertices_Generic_Unlock();
11171 else if (r_showsurfaces.integer == 4)
11173 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11174 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11175 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11177 unsigned char d = (vi << 3) * (1.0f / 256.0f);
11178 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11179 Vector4Set(batchvertex[vi].color4f, d, d, d, 1);
11181 R_Mesh_PrepareVertices_Generic_Unlock();
11184 else if (r_showsurfaces.integer == 2)
11187 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11188 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11189 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11191 unsigned char d = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11192 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11193 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11194 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11195 Vector4Set(batchvertex[j*3+0].color4f, d, d, d, 1);
11196 Vector4Set(batchvertex[j*3+1].color4f, d, d, d, 1);
11197 Vector4Set(batchvertex[j*3+2].color4f, d, d, d, 1);
11199 R_Mesh_PrepareVertices_Generic_Unlock();
11200 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11204 int texturesurfaceindex;
11206 const msurface_t *surface;
11207 float surfacecolor4f[4];
11208 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11209 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11211 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11213 surface = texturesurfacelist[texturesurfaceindex];
11214 k = (int)(((size_t)surface) / sizeof(msurface_t));
11215 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11216 for (j = 0;j < surface->num_vertices;j++)
11218 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11219 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11223 R_Mesh_PrepareVertices_Generic_Unlock();
11228 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11231 RSurf_SetupDepthAndCulling();
11232 if (r_showsurfaces.integer)
11234 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11237 switch (vid.renderpath)
11239 case RENDERPATH_GL20:
11240 case RENDERPATH_D3D9:
11241 case RENDERPATH_D3D10:
11242 case RENDERPATH_D3D11:
11243 case RENDERPATH_SOFT:
11244 case RENDERPATH_GLES2:
11245 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11247 case RENDERPATH_GL13:
11248 case RENDERPATH_GLES1:
11249 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11251 case RENDERPATH_GL11:
11252 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11258 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11261 RSurf_SetupDepthAndCulling();
11262 if (r_showsurfaces.integer)
11264 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11267 switch (vid.renderpath)
11269 case RENDERPATH_GL20:
11270 case RENDERPATH_D3D9:
11271 case RENDERPATH_D3D10:
11272 case RENDERPATH_D3D11:
11273 case RENDERPATH_SOFT:
11274 case RENDERPATH_GLES2:
11275 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11277 case RENDERPATH_GL13:
11278 case RENDERPATH_GLES1:
11279 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11281 case RENDERPATH_GL11:
11282 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11288 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11291 int texturenumsurfaces, endsurface;
11292 texture_t *texture;
11293 const msurface_t *surface;
11294 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11296 // if the model is static it doesn't matter what value we give for
11297 // wantnormals and wanttangents, so this logic uses only rules applicable
11298 // to a model, knowing that they are meaningless otherwise
11299 if (ent == r_refdef.scene.worldentity)
11300 RSurf_ActiveWorldEntity();
11301 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11302 RSurf_ActiveModelEntity(ent, false, false, false);
11305 switch (vid.renderpath)
11307 case RENDERPATH_GL20:
11308 case RENDERPATH_D3D9:
11309 case RENDERPATH_D3D10:
11310 case RENDERPATH_D3D11:
11311 case RENDERPATH_SOFT:
11312 case RENDERPATH_GLES2:
11313 RSurf_ActiveModelEntity(ent, true, true, false);
11315 case RENDERPATH_GL11:
11316 case RENDERPATH_GL13:
11317 case RENDERPATH_GLES1:
11318 RSurf_ActiveModelEntity(ent, true, false, false);
11323 if (r_transparentdepthmasking.integer)
11325 qboolean setup = false;
11326 for (i = 0;i < numsurfaces;i = j)
11329 surface = rsurface.modelsurfaces + surfacelist[i];
11330 texture = surface->texture;
11331 rsurface.texture = R_GetCurrentTexture(texture);
11332 rsurface.lightmaptexture = NULL;
11333 rsurface.deluxemaptexture = NULL;
11334 rsurface.uselightmaptexture = false;
11335 // scan ahead until we find a different texture
11336 endsurface = min(i + 1024, numsurfaces);
11337 texturenumsurfaces = 0;
11338 texturesurfacelist[texturenumsurfaces++] = surface;
11339 for (;j < endsurface;j++)
11341 surface = rsurface.modelsurfaces + surfacelist[j];
11342 if (texture != surface->texture)
11344 texturesurfacelist[texturenumsurfaces++] = surface;
11346 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11348 // render the range of surfaces as depth
11352 GL_ColorMask(0,0,0,0);
11354 GL_DepthTest(true);
11355 GL_BlendFunc(GL_ONE, GL_ZERO);
11356 GL_DepthMask(true);
11357 // R_Mesh_ResetTextureState();
11359 RSurf_SetupDepthAndCulling();
11360 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11361 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11362 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11366 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11369 for (i = 0;i < numsurfaces;i = j)
11372 surface = rsurface.modelsurfaces + surfacelist[i];
11373 texture = surface->texture;
11374 rsurface.texture = R_GetCurrentTexture(texture);
11375 // scan ahead until we find a different texture
11376 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11377 texturenumsurfaces = 0;
11378 texturesurfacelist[texturenumsurfaces++] = surface;
11379 if(FAKELIGHT_ENABLED)
11381 rsurface.lightmaptexture = NULL;
11382 rsurface.deluxemaptexture = NULL;
11383 rsurface.uselightmaptexture = false;
11384 for (;j < endsurface;j++)
11386 surface = rsurface.modelsurfaces + surfacelist[j];
11387 if (texture != surface->texture)
11389 texturesurfacelist[texturenumsurfaces++] = surface;
11394 rsurface.lightmaptexture = surface->lightmaptexture;
11395 rsurface.deluxemaptexture = surface->deluxemaptexture;
11396 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11397 for (;j < endsurface;j++)
11399 surface = rsurface.modelsurfaces + surfacelist[j];
11400 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11402 texturesurfacelist[texturenumsurfaces++] = surface;
11405 // render the range of surfaces
11406 if (ent == r_refdef.scene.worldentity)
11407 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11409 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11411 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11414 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11416 // transparent surfaces get pushed off into the transparent queue
11417 int surfacelistindex;
11418 const msurface_t *surface;
11419 vec3_t tempcenter, center;
11420 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11422 surface = texturesurfacelist[surfacelistindex];
11423 if (r_transparent_sortsurfacesbynearest.integer)
11425 tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11426 tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11427 tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11431 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11432 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11433 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11435 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11436 if (rsurface.entity->transparent_offset) // transparent offset
11438 center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11439 center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11440 center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11442 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);
11446 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11448 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11450 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11452 RSurf_SetupDepthAndCulling();
11453 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11454 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11455 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11459 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11463 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11466 if (!rsurface.texture->currentnumlayers)
11468 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11469 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11471 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11473 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11474 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11475 else if (!rsurface.texture->currentnumlayers)
11477 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11479 // in the deferred case, transparent surfaces were queued during prepass
11480 if (!r_shadow_usingdeferredprepass)
11481 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11485 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11486 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11491 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11494 texture_t *texture;
11495 R_FrameData_SetMark();
11496 // break the surface list down into batches by texture and use of lightmapping
11497 for (i = 0;i < numsurfaces;i = j)
11500 // texture is the base texture pointer, rsurface.texture is the
11501 // current frame/skin the texture is directing us to use (for example
11502 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11503 // use skin 1 instead)
11504 texture = surfacelist[i]->texture;
11505 rsurface.texture = R_GetCurrentTexture(texture);
11506 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11508 // if this texture is not the kind we want, skip ahead to the next one
11509 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11513 if(FAKELIGHT_ENABLED || depthonly || prepass)
11515 rsurface.lightmaptexture = NULL;
11516 rsurface.deluxemaptexture = NULL;
11517 rsurface.uselightmaptexture = false;
11518 // simply scan ahead until we find a different texture or lightmap state
11519 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11524 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11525 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11526 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11527 // simply scan ahead until we find a different texture or lightmap state
11528 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11531 // render the range of surfaces
11532 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11534 R_FrameData_ReturnToMark();
11537 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11541 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11544 if (!rsurface.texture->currentnumlayers)
11546 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11547 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11549 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11551 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11552 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11553 else if (!rsurface.texture->currentnumlayers)
11555 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11557 // in the deferred case, transparent surfaces were queued during prepass
11558 if (!r_shadow_usingdeferredprepass)
11559 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11563 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11564 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11569 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11572 texture_t *texture;
11573 R_FrameData_SetMark();
11574 // break the surface list down into batches by texture and use of lightmapping
11575 for (i = 0;i < numsurfaces;i = j)
11578 // texture is the base texture pointer, rsurface.texture is the
11579 // current frame/skin the texture is directing us to use (for example
11580 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11581 // use skin 1 instead)
11582 texture = surfacelist[i]->texture;
11583 rsurface.texture = R_GetCurrentTexture(texture);
11584 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11586 // if this texture is not the kind we want, skip ahead to the next one
11587 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11591 if(FAKELIGHT_ENABLED || depthonly || prepass)
11593 rsurface.lightmaptexture = NULL;
11594 rsurface.deluxemaptexture = NULL;
11595 rsurface.uselightmaptexture = false;
11596 // simply scan ahead until we find a different texture or lightmap state
11597 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11602 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11603 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11604 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11605 // simply scan ahead until we find a different texture or lightmap state
11606 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11609 // render the range of surfaces
11610 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11612 R_FrameData_ReturnToMark();
11615 float locboxvertex3f[6*4*3] =
11617 1,0,1, 1,0,0, 1,1,0, 1,1,1,
11618 0,1,1, 0,1,0, 0,0,0, 0,0,1,
11619 1,1,1, 1,1,0, 0,1,0, 0,1,1,
11620 0,0,1, 0,0,0, 1,0,0, 1,0,1,
11621 0,0,1, 1,0,1, 1,1,1, 0,1,1,
11622 1,0,0, 0,0,0, 0,1,0, 1,1,0
11625 unsigned short locboxelements[6*2*3] =
11630 12,13,14, 12,14,15,
11631 16,17,18, 16,18,19,
11635 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11638 cl_locnode_t *loc = (cl_locnode_t *)ent;
11640 float vertex3f[6*4*3];
11642 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11643 GL_DepthMask(false);
11644 GL_DepthRange(0, 1);
11645 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11646 GL_DepthTest(true);
11647 GL_CullFace(GL_NONE);
11648 R_EntityMatrix(&identitymatrix);
11650 // R_Mesh_ResetTextureState();
11652 i = surfacelist[0];
11653 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11654 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11655 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11656 surfacelist[0] < 0 ? 0.5f : 0.125f);
11658 if (VectorCompare(loc->mins, loc->maxs))
11660 VectorSet(size, 2, 2, 2);
11661 VectorMA(loc->mins, -0.5f, size, mins);
11665 VectorCopy(loc->mins, mins);
11666 VectorSubtract(loc->maxs, loc->mins, size);
11669 for (i = 0;i < 6*4*3;)
11670 for (j = 0;j < 3;j++, i++)
11671 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11673 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11674 R_SetupShader_Generic_NoTexture(false, false);
11675 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11678 void R_DrawLocs(void)
11681 cl_locnode_t *loc, *nearestloc;
11683 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11684 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11686 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11687 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11691 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11693 if (decalsystem->decals)
11694 Mem_Free(decalsystem->decals);
11695 memset(decalsystem, 0, sizeof(*decalsystem));
11698 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)
11701 tridecal_t *decals;
11704 // expand or initialize the system
11705 if (decalsystem->maxdecals <= decalsystem->numdecals)
11707 decalsystem_t old = *decalsystem;
11708 qboolean useshortelements;
11709 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11710 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11711 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)));
11712 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11713 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11714 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11715 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11716 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11717 if (decalsystem->numdecals)
11718 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11720 Mem_Free(old.decals);
11721 for (i = 0;i < decalsystem->maxdecals*3;i++)
11722 decalsystem->element3i[i] = i;
11723 if (useshortelements)
11724 for (i = 0;i < decalsystem->maxdecals*3;i++)
11725 decalsystem->element3s[i] = i;
11728 // grab a decal and search for another free slot for the next one
11729 decals = decalsystem->decals;
11730 decal = decalsystem->decals + (i = decalsystem->freedecal++);
11731 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11733 decalsystem->freedecal = i;
11734 if (decalsystem->numdecals <= i)
11735 decalsystem->numdecals = i + 1;
11737 // initialize the decal
11739 decal->triangleindex = triangleindex;
11740 decal->surfaceindex = surfaceindex;
11741 decal->decalsequence = decalsequence;
11742 decal->color4f[0][0] = c0[0];
11743 decal->color4f[0][1] = c0[1];
11744 decal->color4f[0][2] = c0[2];
11745 decal->color4f[0][3] = 1;
11746 decal->color4f[1][0] = c1[0];
11747 decal->color4f[1][1] = c1[1];
11748 decal->color4f[1][2] = c1[2];
11749 decal->color4f[1][3] = 1;
11750 decal->color4f[2][0] = c2[0];
11751 decal->color4f[2][1] = c2[1];
11752 decal->color4f[2][2] = c2[2];
11753 decal->color4f[2][3] = 1;
11754 decal->vertex3f[0][0] = v0[0];
11755 decal->vertex3f[0][1] = v0[1];
11756 decal->vertex3f[0][2] = v0[2];
11757 decal->vertex3f[1][0] = v1[0];
11758 decal->vertex3f[1][1] = v1[1];
11759 decal->vertex3f[1][2] = v1[2];
11760 decal->vertex3f[2][0] = v2[0];
11761 decal->vertex3f[2][1] = v2[1];
11762 decal->vertex3f[2][2] = v2[2];
11763 decal->texcoord2f[0][0] = t0[0];
11764 decal->texcoord2f[0][1] = t0[1];
11765 decal->texcoord2f[1][0] = t1[0];
11766 decal->texcoord2f[1][1] = t1[1];
11767 decal->texcoord2f[2][0] = t2[0];
11768 decal->texcoord2f[2][1] = t2[1];
11769 TriangleNormal(v0, v1, v2, decal->plane);
11770 VectorNormalize(decal->plane);
11771 decal->plane[3] = DotProduct(v0, decal->plane);
11774 extern cvar_t cl_decals_bias;
11775 extern cvar_t cl_decals_models;
11776 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11777 // baseparms, parms, temps
11778 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)
11783 const float *vertex3f;
11784 const float *normal3f;
11786 float points[2][9][3];
11793 e = rsurface.modelelement3i + 3*triangleindex;
11795 vertex3f = rsurface.modelvertex3f;
11796 normal3f = rsurface.modelnormal3f;
11800 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11802 index = 3*e[cornerindex];
11803 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11808 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11810 index = 3*e[cornerindex];
11811 VectorCopy(vertex3f + index, v[cornerindex]);
11816 //TriangleNormal(v[0], v[1], v[2], normal);
11817 //if (DotProduct(normal, localnormal) < 0.0f)
11819 // clip by each of the box planes formed from the projection matrix
11820 // if anything survives, we emit the decal
11821 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]);
11824 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]);
11827 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]);
11830 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]);
11833 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]);
11836 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]);
11839 // some part of the triangle survived, so we have to accept it...
11842 // dynamic always uses the original triangle
11844 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11846 index = 3*e[cornerindex];
11847 VectorCopy(vertex3f + index, v[cornerindex]);
11850 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11852 // convert vertex positions to texcoords
11853 Matrix4x4_Transform(projection, v[cornerindex], temp);
11854 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11855 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11856 // calculate distance fade from the projection origin
11857 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11858 f = bound(0.0f, f, 1.0f);
11859 c[cornerindex][0] = r * f;
11860 c[cornerindex][1] = g * f;
11861 c[cornerindex][2] = b * f;
11862 c[cornerindex][3] = 1.0f;
11863 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11866 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);
11868 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11869 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);
11871 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)
11873 matrix4x4_t projection;
11874 decalsystem_t *decalsystem;
11877 const msurface_t *surface;
11878 const msurface_t *surfaces;
11879 const int *surfacelist;
11880 const texture_t *texture;
11882 int numsurfacelist;
11883 int surfacelistindex;
11886 float localorigin[3];
11887 float localnormal[3];
11888 float localmins[3];
11889 float localmaxs[3];
11892 float planes[6][4];
11895 int bih_triangles_count;
11896 int bih_triangles[256];
11897 int bih_surfaces[256];
11899 decalsystem = &ent->decalsystem;
11900 model = ent->model;
11901 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11903 R_DecalSystem_Reset(&ent->decalsystem);
11907 if (!model->brush.data_leafs && !cl_decals_models.integer)
11909 if (decalsystem->model)
11910 R_DecalSystem_Reset(decalsystem);
11914 if (decalsystem->model != model)
11915 R_DecalSystem_Reset(decalsystem);
11916 decalsystem->model = model;
11918 RSurf_ActiveModelEntity(ent, true, false, false);
11920 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11921 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11922 VectorNormalize(localnormal);
11923 localsize = worldsize*rsurface.inversematrixscale;
11924 localmins[0] = localorigin[0] - localsize;
11925 localmins[1] = localorigin[1] - localsize;
11926 localmins[2] = localorigin[2] - localsize;
11927 localmaxs[0] = localorigin[0] + localsize;
11928 localmaxs[1] = localorigin[1] + localsize;
11929 localmaxs[2] = localorigin[2] + localsize;
11931 //VectorCopy(localnormal, planes[4]);
11932 //VectorVectors(planes[4], planes[2], planes[0]);
11933 AnglesFromVectors(angles, localnormal, NULL, false);
11934 AngleVectors(angles, planes[0], planes[2], planes[4]);
11935 VectorNegate(planes[0], planes[1]);
11936 VectorNegate(planes[2], planes[3]);
11937 VectorNegate(planes[4], planes[5]);
11938 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11939 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11940 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11941 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11942 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11943 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11948 matrix4x4_t forwardprojection;
11949 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11950 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11955 float projectionvector[4][3];
11956 VectorScale(planes[0], ilocalsize, projectionvector[0]);
11957 VectorScale(planes[2], ilocalsize, projectionvector[1]);
11958 VectorScale(planes[4], ilocalsize, projectionvector[2]);
11959 projectionvector[0][0] = planes[0][0] * ilocalsize;
11960 projectionvector[0][1] = planes[1][0] * ilocalsize;
11961 projectionvector[0][2] = planes[2][0] * ilocalsize;
11962 projectionvector[1][0] = planes[0][1] * ilocalsize;
11963 projectionvector[1][1] = planes[1][1] * ilocalsize;
11964 projectionvector[1][2] = planes[2][1] * ilocalsize;
11965 projectionvector[2][0] = planes[0][2] * ilocalsize;
11966 projectionvector[2][1] = planes[1][2] * ilocalsize;
11967 projectionvector[2][2] = planes[2][2] * ilocalsize;
11968 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11969 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11970 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11971 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11975 dynamic = model->surfmesh.isanimated;
11976 numsurfacelist = model->nummodelsurfaces;
11977 surfacelist = model->sortedmodelsurfaces;
11978 surfaces = model->data_surfaces;
11981 bih_triangles_count = -1;
11984 if(model->render_bih.numleafs)
11985 bih = &model->render_bih;
11986 else if(model->collision_bih.numleafs)
11987 bih = &model->collision_bih;
11990 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11991 if(bih_triangles_count == 0)
11993 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11995 if(bih_triangles_count > 0)
11997 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11999 surfaceindex = bih_surfaces[triangleindex];
12000 surface = surfaces + surfaceindex;
12001 texture = surface->texture;
12002 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
12004 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
12006 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
12011 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
12013 surfaceindex = surfacelist[surfacelistindex];
12014 surface = surfaces + surfaceindex;
12015 // check cull box first because it rejects more than any other check
12016 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
12018 // skip transparent surfaces
12019 texture = surface->texture;
12020 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
12022 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
12024 numtriangles = surface->num_triangles;
12025 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
12026 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
12031 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
12032 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)
12034 int renderentityindex;
12035 float worldmins[3];
12036 float worldmaxs[3];
12037 entity_render_t *ent;
12039 if (!cl_decals_newsystem.integer)
12042 worldmins[0] = worldorigin[0] - worldsize;
12043 worldmins[1] = worldorigin[1] - worldsize;
12044 worldmins[2] = worldorigin[2] - worldsize;
12045 worldmaxs[0] = worldorigin[0] + worldsize;
12046 worldmaxs[1] = worldorigin[1] + worldsize;
12047 worldmaxs[2] = worldorigin[2] + worldsize;
12049 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12051 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
12053 ent = r_refdef.scene.entities[renderentityindex];
12054 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
12057 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12061 typedef struct r_decalsystem_splatqueue_s
12063 vec3_t worldorigin;
12064 vec3_t worldnormal;
12068 unsigned int decalsequence;
12070 r_decalsystem_splatqueue_t;
12072 int r_decalsystem_numqueued = 0;
12073 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
12075 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)
12077 r_decalsystem_splatqueue_t *queue;
12079 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
12082 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
12083 VectorCopy(worldorigin, queue->worldorigin);
12084 VectorCopy(worldnormal, queue->worldnormal);
12085 Vector4Set(queue->color, r, g, b, a);
12086 Vector4Set(queue->tcrange, s1, t1, s2, t2);
12087 queue->worldsize = worldsize;
12088 queue->decalsequence = cl.decalsequence++;
12091 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
12094 r_decalsystem_splatqueue_t *queue;
12096 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
12097 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);
12098 r_decalsystem_numqueued = 0;
12101 extern cvar_t cl_decals_max;
12102 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12105 decalsystem_t *decalsystem = &ent->decalsystem;
12107 unsigned int killsequence;
12112 if (!decalsystem->numdecals)
12115 if (r_showsurfaces.integer)
12118 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12120 R_DecalSystem_Reset(decalsystem);
12124 killsequence = cl.decalsequence - bound(1, (unsigned int) cl_decals_max.integer, cl.decalsequence);
12125 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12127 if (decalsystem->lastupdatetime)
12128 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
12131 decalsystem->lastupdatetime = r_refdef.scene.time;
12132 numdecals = decalsystem->numdecals;
12134 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12136 if (decal->color4f[0][3])
12138 decal->lived += frametime;
12139 if (killsequence > decal->decalsequence || decal->lived >= lifetime)
12141 memset(decal, 0, sizeof(*decal));
12142 if (decalsystem->freedecal > i)
12143 decalsystem->freedecal = i;
12147 decal = decalsystem->decals;
12148 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
12151 // collapse the array by shuffling the tail decals into the gaps
12154 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
12155 decalsystem->freedecal++;
12156 if (decalsystem->freedecal == numdecals)
12158 decal[decalsystem->freedecal] = decal[--numdecals];
12161 decalsystem->numdecals = numdecals;
12163 if (numdecals <= 0)
12165 // if there are no decals left, reset decalsystem
12166 R_DecalSystem_Reset(decalsystem);
12170 extern skinframe_t *decalskinframe;
12171 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12174 decalsystem_t *decalsystem = &ent->decalsystem;
12183 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12186 numdecals = decalsystem->numdecals;
12190 if (r_showsurfaces.integer)
12193 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12195 R_DecalSystem_Reset(decalsystem);
12199 // if the model is static it doesn't matter what value we give for
12200 // wantnormals and wanttangents, so this logic uses only rules applicable
12201 // to a model, knowing that they are meaningless otherwise
12202 if (ent == r_refdef.scene.worldentity)
12203 RSurf_ActiveWorldEntity();
12205 RSurf_ActiveModelEntity(ent, false, false, false);
12207 decalsystem->lastupdatetime = r_refdef.scene.time;
12209 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12211 // update vertex positions for animated models
12212 v3f = decalsystem->vertex3f;
12213 c4f = decalsystem->color4f;
12214 t2f = decalsystem->texcoord2f;
12215 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12217 if (!decal->color4f[0][3])
12220 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12224 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
12227 // update color values for fading decals
12228 if (decal->lived >= cl_decals_time.value)
12229 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12233 c4f[ 0] = decal->color4f[0][0] * alpha;
12234 c4f[ 1] = decal->color4f[0][1] * alpha;
12235 c4f[ 2] = decal->color4f[0][2] * alpha;
12237 c4f[ 4] = decal->color4f[1][0] * alpha;
12238 c4f[ 5] = decal->color4f[1][1] * alpha;
12239 c4f[ 6] = decal->color4f[1][2] * alpha;
12241 c4f[ 8] = decal->color4f[2][0] * alpha;
12242 c4f[ 9] = decal->color4f[2][1] * alpha;
12243 c4f[10] = decal->color4f[2][2] * alpha;
12246 t2f[0] = decal->texcoord2f[0][0];
12247 t2f[1] = decal->texcoord2f[0][1];
12248 t2f[2] = decal->texcoord2f[1][0];
12249 t2f[3] = decal->texcoord2f[1][1];
12250 t2f[4] = decal->texcoord2f[2][0];
12251 t2f[5] = decal->texcoord2f[2][1];
12253 // update vertex positions for animated models
12254 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12256 e = rsurface.modelelement3i + 3*decal->triangleindex;
12257 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12258 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12259 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12263 VectorCopy(decal->vertex3f[0], v3f);
12264 VectorCopy(decal->vertex3f[1], v3f + 3);
12265 VectorCopy(decal->vertex3f[2], v3f + 6);
12268 if (r_refdef.fogenabled)
12270 alpha = RSurf_FogVertex(v3f);
12271 VectorScale(c4f, alpha, c4f);
12272 alpha = RSurf_FogVertex(v3f + 3);
12273 VectorScale(c4f + 4, alpha, c4f + 4);
12274 alpha = RSurf_FogVertex(v3f + 6);
12275 VectorScale(c4f + 8, alpha, c4f + 8);
12286 r_refdef.stats[r_stat_drawndecals] += numtris;
12288 // now render the decals all at once
12289 // (this assumes they all use one particle font texture!)
12290 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);
12291 // R_Mesh_ResetTextureState();
12292 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12293 GL_DepthMask(false);
12294 GL_DepthRange(0, 1);
12295 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12296 GL_DepthTest(true);
12297 GL_CullFace(GL_NONE);
12298 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12299 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12300 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12304 static void R_DrawModelDecals(void)
12308 // fade faster when there are too many decals
12309 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12310 for (i = 0;i < r_refdef.scene.numentities;i++)
12311 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12313 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12314 for (i = 0;i < r_refdef.scene.numentities;i++)
12315 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12316 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12318 R_DecalSystem_ApplySplatEntitiesQueue();
12320 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12321 for (i = 0;i < r_refdef.scene.numentities;i++)
12322 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12324 r_refdef.stats[r_stat_totaldecals] += numdecals;
12326 if (r_showsurfaces.integer)
12329 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12331 for (i = 0;i < r_refdef.scene.numentities;i++)
12333 if (!r_refdef.viewcache.entityvisible[i])
12335 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12336 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12340 extern cvar_t mod_collision_bih;
12341 static void R_DrawDebugModel(void)
12343 entity_render_t *ent = rsurface.entity;
12344 int i, j, flagsmask;
12345 const msurface_t *surface;
12346 dp_model_t *model = ent->model;
12348 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12351 if (r_showoverdraw.value > 0)
12353 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12354 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12355 R_SetupShader_Generic_NoTexture(false, false);
12356 GL_DepthTest(false);
12357 GL_DepthMask(false);
12358 GL_DepthRange(0, 1);
12359 GL_BlendFunc(GL_ONE, GL_ONE);
12360 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12362 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12364 rsurface.texture = R_GetCurrentTexture(surface->texture);
12365 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12367 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12368 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12369 if (!rsurface.texture->currentlayers->depthmask)
12370 GL_Color(c, 0, 0, 1.0f);
12371 else if (ent == r_refdef.scene.worldentity)
12372 GL_Color(c, c, c, 1.0f);
12374 GL_Color(0, c, 0, 1.0f);
12375 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12379 rsurface.texture = NULL;
12382 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12384 // R_Mesh_ResetTextureState();
12385 R_SetupShader_Generic_NoTexture(false, false);
12386 GL_DepthRange(0, 1);
12387 GL_DepthTest(!r_showdisabledepthtest.integer);
12388 GL_DepthMask(false);
12389 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12391 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12395 qboolean cullbox = false;
12396 const q3mbrush_t *brush;
12397 const bih_t *bih = &model->collision_bih;
12398 const bih_leaf_t *bihleaf;
12399 float vertex3f[3][3];
12400 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12401 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12403 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12405 switch (bihleaf->type)
12408 brush = model->brush.data_brushes + bihleaf->itemindex;
12409 if (brush->colbrushf && brush->colbrushf->numtriangles)
12411 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);
12412 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12413 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12416 case BIH_COLLISIONTRIANGLE:
12417 triangleindex = bihleaf->itemindex;
12418 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12419 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12420 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12421 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);
12422 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12423 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12425 case BIH_RENDERTRIANGLE:
12426 triangleindex = bihleaf->itemindex;
12427 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12428 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12429 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12430 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);
12431 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12432 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12438 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12441 if (r_showtris.integer && qglPolygonMode)
12443 if (r_showdisabledepthtest.integer)
12445 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12446 GL_DepthMask(false);
12450 GL_BlendFunc(GL_ONE, GL_ZERO);
12451 GL_DepthMask(true);
12453 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12454 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12456 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12458 rsurface.texture = R_GetCurrentTexture(surface->texture);
12459 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12461 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12462 if (!rsurface.texture->currentlayers->depthmask)
12463 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12464 else if (ent == r_refdef.scene.worldentity)
12465 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12467 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12468 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12472 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12473 rsurface.texture = NULL;
12476 if (r_shownormals.value != 0 && qglBegin)
12480 if (r_showdisabledepthtest.integer)
12482 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12483 GL_DepthMask(false);
12487 GL_BlendFunc(GL_ONE, GL_ZERO);
12488 GL_DepthMask(true);
12490 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12492 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12494 rsurface.texture = R_GetCurrentTexture(surface->texture);
12495 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12497 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12498 qglBegin(GL_LINES);
12499 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12501 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12503 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12504 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12505 qglVertex3f(v[0], v[1], v[2]);
12506 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12507 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12508 qglVertex3f(v[0], v[1], v[2]);
12511 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12513 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12515 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12516 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12517 qglVertex3f(v[0], v[1], v[2]);
12518 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12519 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12520 qglVertex3f(v[0], v[1], v[2]);
12523 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12525 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12527 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12528 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12529 qglVertex3f(v[0], v[1], v[2]);
12530 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12531 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12532 qglVertex3f(v[0], v[1], v[2]);
12535 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12537 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12539 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12540 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12541 qglVertex3f(v[0], v[1], v[2]);
12542 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12543 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12544 qglVertex3f(v[0], v[1], v[2]);
12551 rsurface.texture = NULL;
12556 int r_maxsurfacelist = 0;
12557 const msurface_t **r_surfacelist = NULL;
12558 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12560 int i, j, endj, flagsmask;
12561 dp_model_t *model = r_refdef.scene.worldmodel;
12562 msurface_t *surfaces;
12563 unsigned char *update;
12564 int numsurfacelist = 0;
12568 if (r_maxsurfacelist < model->num_surfaces)
12570 r_maxsurfacelist = model->num_surfaces;
12572 Mem_Free((msurface_t**)r_surfacelist);
12573 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12576 RSurf_ActiveWorldEntity();
12578 surfaces = model->data_surfaces;
12579 update = model->brushq1.lightmapupdateflags;
12581 // update light styles on this submodel
12582 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12584 model_brush_lightstyleinfo_t *style;
12585 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12587 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12589 int *list = style->surfacelist;
12590 style->value = r_refdef.scene.lightstylevalue[style->style];
12591 for (j = 0;j < style->numsurfaces;j++)
12592 update[list[j]] = true;
12597 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12601 R_DrawDebugModel();
12602 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12606 rsurface.lightmaptexture = NULL;
12607 rsurface.deluxemaptexture = NULL;
12608 rsurface.uselightmaptexture = false;
12609 rsurface.texture = NULL;
12610 rsurface.rtlight = NULL;
12611 numsurfacelist = 0;
12612 // add visible surfaces to draw list
12613 for (i = 0;i < model->nummodelsurfaces;i++)
12615 j = model->sortedmodelsurfaces[i];
12616 if (r_refdef.viewcache.world_surfacevisible[j])
12617 r_surfacelist[numsurfacelist++] = surfaces + j;
12619 // update lightmaps if needed
12620 if (model->brushq1.firstrender)
12622 model->brushq1.firstrender = false;
12623 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12625 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12629 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12630 if (r_refdef.viewcache.world_surfacevisible[j])
12632 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12634 // don't do anything if there were no surfaces
12635 if (!numsurfacelist)
12637 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12640 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12642 // add to stats if desired
12643 if (r_speeds.integer && !skysurfaces && !depthonly)
12645 r_refdef.stats[r_stat_world_surfaces] += numsurfacelist;
12646 for (j = 0;j < numsurfacelist;j++)
12647 r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles;
12650 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12653 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12655 int i, j, endj, flagsmask;
12656 dp_model_t *model = ent->model;
12657 msurface_t *surfaces;
12658 unsigned char *update;
12659 int numsurfacelist = 0;
12663 if (r_maxsurfacelist < model->num_surfaces)
12665 r_maxsurfacelist = model->num_surfaces;
12667 Mem_Free((msurface_t **)r_surfacelist);
12668 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12671 // if the model is static it doesn't matter what value we give for
12672 // wantnormals and wanttangents, so this logic uses only rules applicable
12673 // to a model, knowing that they are meaningless otherwise
12674 if (ent == r_refdef.scene.worldentity)
12675 RSurf_ActiveWorldEntity();
12676 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12677 RSurf_ActiveModelEntity(ent, false, false, false);
12679 RSurf_ActiveModelEntity(ent, true, true, true);
12680 else if (depthonly)
12682 switch (vid.renderpath)
12684 case RENDERPATH_GL20:
12685 case RENDERPATH_D3D9:
12686 case RENDERPATH_D3D10:
12687 case RENDERPATH_D3D11:
12688 case RENDERPATH_SOFT:
12689 case RENDERPATH_GLES2:
12690 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12692 case RENDERPATH_GL11:
12693 case RENDERPATH_GL13:
12694 case RENDERPATH_GLES1:
12695 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12701 switch (vid.renderpath)
12703 case RENDERPATH_GL20:
12704 case RENDERPATH_D3D9:
12705 case RENDERPATH_D3D10:
12706 case RENDERPATH_D3D11:
12707 case RENDERPATH_SOFT:
12708 case RENDERPATH_GLES2:
12709 RSurf_ActiveModelEntity(ent, true, true, false);
12711 case RENDERPATH_GL11:
12712 case RENDERPATH_GL13:
12713 case RENDERPATH_GLES1:
12714 RSurf_ActiveModelEntity(ent, true, false, false);
12719 surfaces = model->data_surfaces;
12720 update = model->brushq1.lightmapupdateflags;
12722 // update light styles
12723 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12725 model_brush_lightstyleinfo_t *style;
12726 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12728 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12730 int *list = style->surfacelist;
12731 style->value = r_refdef.scene.lightstylevalue[style->style];
12732 for (j = 0;j < style->numsurfaces;j++)
12733 update[list[j]] = true;
12738 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12742 R_DrawDebugModel();
12743 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12747 rsurface.lightmaptexture = NULL;
12748 rsurface.deluxemaptexture = NULL;
12749 rsurface.uselightmaptexture = false;
12750 rsurface.texture = NULL;
12751 rsurface.rtlight = NULL;
12752 numsurfacelist = 0;
12753 // add visible surfaces to draw list
12754 for (i = 0;i < model->nummodelsurfaces;i++)
12755 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12756 // don't do anything if there were no surfaces
12757 if (!numsurfacelist)
12759 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12762 // update lightmaps if needed
12766 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12771 R_BuildLightMap(ent, surfaces + j);
12776 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12778 // add to stats if desired
12779 if (r_speeds.integer && !skysurfaces && !depthonly)
12781 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12782 for (j = 0;j < numsurfacelist;j++)
12783 r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12786 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12789 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12791 static texture_t texture;
12792 static msurface_t surface;
12793 const msurface_t *surfacelist = &surface;
12795 // fake enough texture and surface state to render this geometry
12797 texture.update_lastrenderframe = -1; // regenerate this texture
12798 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12799 texture.basealpha = 1.0f;
12800 texture.currentskinframe = skinframe;
12801 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12802 texture.offsetmapping = OFFSETMAPPING_OFF;
12803 texture.offsetscale = 1;
12804 texture.specularscalemod = 1;
12805 texture.specularpowermod = 1;
12806 texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12807 // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12808 // JUST GREP FOR "specularscalemod = 1".
12810 surface.texture = &texture;
12811 surface.num_triangles = numtriangles;
12812 surface.num_firsttriangle = firsttriangle;
12813 surface.num_vertices = numvertices;
12814 surface.num_firstvertex = firstvertex;
12817 rsurface.texture = R_GetCurrentTexture(surface.texture);
12818 rsurface.lightmaptexture = NULL;
12819 rsurface.deluxemaptexture = NULL;
12820 rsurface.uselightmaptexture = false;
12821 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12824 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)
12826 static msurface_t surface;
12827 const msurface_t *surfacelist = &surface;
12829 // fake enough texture and surface state to render this geometry
12830 surface.texture = texture;
12831 surface.num_triangles = numtriangles;
12832 surface.num_firsttriangle = firsttriangle;
12833 surface.num_vertices = numvertices;
12834 surface.num_firstvertex = firstvertex;
12837 rsurface.texture = R_GetCurrentTexture(surface.texture);
12838 rsurface.lightmaptexture = NULL;
12839 rsurface.deluxemaptexture = NULL;
12840 rsurface.uselightmaptexture = false;
12841 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);