Last active
February 6, 2022 06:46
-
-
Save QuadStorm/ddb7ecce4658ae48ab6b0dbc6b6ba430 to your computer and use it in GitHub Desktop.
Contact-Hardening Soft Shadows for Blockland - Soft shadows that realistically soften or harden based on distance (NVIDIA version)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#version 120 | |
#extension GL_EXT_texture_array : require | |
#extension GL_EXT_texture_array : enable | |
// Originally Port's Poisson Disc (Optimized) Soft Shadow Shader (2015), modified by Stealth Commander/QuadStorm | |
// Includes a Contact-Hardening/Percentage-Closer/Perceptually-Correct Soft Shadows (CHSS/PCSS) implementation, and other many configurable variables | |
// 10th version | |
// Configuration: For the adventurous! | |
// Perfection can be hard to come by. You'll probably have to tweak settings per situation to get things right. | |
// Shadows | |
// Ignore any soft shadow settings and use default shader shadowing | |
bool defaultShadows = false; | |
// Shadow Opacity Adjustment; blend between minimum shading and full shadows | |
// Allows for changing how transparent/opaque shadows are -- see https://forum.blockland.us/index.php?topic=289446.0; this toggles the 'fix' | |
bool shadowOpacity = true; | |
// occlusionBlend - strength of above effect, where 1.0f is no effect (default opaque), and 0.0f is the same as minimum shaders (no shadows) | |
float occlusionBlend = 0.9f; | |
// This is blending. Shadows are rendered to separate layers based on distance. | |
// This may cause shadows to suddenly change appearance. Use this to change | |
// how long a distance they will "fade" between the two versions over. | |
float blendAlpha = 0.9f; // bl default is 0.9f | |
float blendBeta = 1.0f - blendAlpha; | |
// These values are very important. If they're too low, you will see weird | |
// patterns and waves everywhere. If they're too high, shadows will be | |
// disconnected from their objects. They need to be adjusted carefully. | |
// These are set specifically for Max quality with max drawing distance. | |
// You'll need to change them based on your shader quality (and if you changed | |
// the Poisson disk below.. probably). | |
///* | |
const float fudgeFactor1 = 0.2f; //0.15f | |
const float fudgeFactor2 = 0.5f; //0.375f | |
const float fudgeFactor3 = 1.3f; //1.05f | |
const float fudgeFactor4 = 5.0f; //4.0f | |
/* | |
const float fudgeFactor1 = 0.1f; | |
const float fudgeFactor2 = 0.25f; | |
const float fudgeFactor3 = 0.7f; | |
const float fudgeFactor4 = 2.66f; | |
*/// | |
// Dynamic Fudge Factor based upon https://learnopengl.com/Advanced-Lighting/Shadows/Shadow-Mapping; disable to counter shadow peterpanning instead of acne | |
bool dynamicFF = true; | |
// How much more the fudge factor changes with angle | |
float dynamicFudgeFactor = 3.5f; | |
// How soft should the shadows be? (how far out does the edge go) | |
// Change this or the magic numbers below to improve your "softness" quality | |
// note that fancy powers of two aren't needed, but they can be good starting points | |
float sampleDistance = 1.0f / 1000.0f; | |
// Cascaded Shadow Map adjustment | |
// Changes shadow softness to be roughly equal for each shadow cascade | |
bool csmAdjustmentEnabled = true; | |
// Ultra Mode; recomended to have CHSS off if you use this but you can have both if you must | |
// Uses 2 shadow sample layers ontop of eachother for an 'ultra' graphics effect | |
bool ultra = false; | |
// ultraRatio - ratio in size between the normal and ambient samples | |
float ultraRatio = 5.0f; | |
// tune the 'ultra' shader effect a bit | |
// > 0.5f weighs the small sample more, while < 0.5f weighs the large sample more | |
// values too close to either 0.0f or 1.0f make the effect too subtle and defeat the purpose of ultra mode | |
float ultraWeightFactor = 0.4f; | |
// Contact-Hardening Soft Shadows | |
// Variable shadow penumbra by distance (sampleDistance above ignored) | |
bool CHSS = true; | |
// Which algorithm to use for the blocker search | |
// 0 - Square, 1 - Poisson, 2 - Vogel | |
int blockerSearchMethod = 2; | |
// Basic Square blocker search loops - 1 = 3x3, 2 = 5x5, 3 = 7x7, etc. | |
int blockerSearchSquareNum = 3; | |
// Vogel Disk Sample Count for the blocker search | |
int VogelDiskSearchSampleCount = 8; | |
// Interleaved Gradient Noise for the Vogel disk blocker search | |
bool InterleavedGradientNoiseSearchEnabled = true; | |
// Whether to use the near plane for the CHSS blocker depth search radius | |
bool searchDistanceNearPlane = false; | |
// if above bool is false, this distance is used | |
float blockerSearchDistance = 1.0f / 50.0f; | |
// if above bool is true, nearPlane for similar triangles blocker search | |
float nearPlane = 0.46f; | |
// whether to adjust the blocker search distances by shadow cascades (similar to csmAdjustmentEnabled) | |
bool blockerSearchAdjustment = true; | |
// How large the light source is -- affects how quickly shadows become soft with distance; change as needed with context (0.005f - 0.25f) | |
float lightSize = 0.2f; | |
// CHSS penumbra size minimum, which will be added to the computed penumbra size | |
bool chssMinRadius = false; | |
float chssMinPenumbraRadius = 1.0f / 5000.0f; // 5000 | 0.0002 | |
// CHSS penumbra size maximum, that will only allows shadows to match the size of the blocker search | |
bool chssMaxRadius = true; | |
// Which algorithm to use for PCF (for CHSS and regular fixed penumbra size soft shadows) | |
// 0 - Square, 1 - Poisson Disk, 2 - Square and Poisson (if you want to for some weird reason have the appearance of both for double the performance impact), 3 - Vogel Disk | |
int pcfMethod = 3; | |
// Ratio between Square and Poisson filtering if Both option is selected; 0.0f = 100% Poisson, 1.0f = 100% Square | |
float pcfBlend = 0.4f; | |
// Basic Square filtering loops - 1 = 3x3, 2 = 5x5, 3 = 7x7, ... | |
int squareFilteringNum = 3; | |
// Vogel Disk Sample Count for the shadow filtering | |
int VogelDiskFilterSampleCount = 8; | |
// Interleaved Gradient Noise for the Vogel disk shadow filtering | |
bool InterleavedGradientNoiseFilteringEnabled = true; | |
// Interleaved Gradient Noise pattern tuning (blocker search and shadow filtering) | |
int InterleavedGradientNoiseFactor = 10000; | |
// Magic numbers below | |
/* | |
int poissonDiskCount = 24; | |
vec2 poissonDisk[24] = vec2[]( | |
vec2(0.01020043f, 0.3103616f), | |
vec2(-0.4121873f, -0.1701329f), | |
vec2(0.4333374f, 0.6148015f), | |
vec2(0.1092096f, -0.2437763f), | |
vec2(0.6641068f, -0.1210794f), | |
vec2(-0.1726627f, 0.8724736f), | |
vec2(-0.8549297f, 0.2836411f), | |
vec2(0.5146544f, -0.6802685f), | |
vec2(0.04769185f, -0.879628f), | |
vec2(-0.9373617f, -0.2187589f), | |
vec2(-0.69226f, -0.6652822f), | |
vec2(0.9230682f, 0.3181772f), | |
// these points might be bad: | |
vec2(-0.1565961f, 0.8773971f), | |
vec2(-0.5258075f, 0.3916658f), | |
vec2(0.515902f, 0.3077986f), | |
vec2(-0.006838934f, 0.2577735f), | |
vec2(-0.9315282f, -0.04518054f), | |
vec2(-0.3417063f, -0.1195169f), | |
vec2(-0.3221133f, -0.8118886f), | |
vec2(0.425082f, -0.3786222f), | |
vec2(0.3917231f, 0.9194779f), | |
vec2(0.8819267f, -0.1306234f), | |
vec2(-0.7906089f, -0.5639677f), | |
vec2(0.2073919f, -0.9611396f) | |
); | |
//*/ | |
/* | |
int poissonDiskCount = 32; | |
vec2 poissonDisk[32] = vec2[] | |
( | |
vec2(0.6037009, -0.3977135), | |
vec2(0.1432971, -0.5475889), | |
vec2(0.4130006, -0.6745455), | |
vec2(0.9136397, -0.1000729), | |
vec2(0.5681907, -0.1194669), | |
vec2(0.7630879, -0.6211567), | |
vec2(0.1874292, -0.1614596), | |
vec2(-0.06089688, -0.9141597), | |
vec2(0.2590805, -0.9208742), | |
vec2(-0.3907768, -0.594767), | |
vec2(0.9119951, -0.3819307), | |
vec2(-0.3664423, -0.9234819), | |
vec2(-0.09851982, -0.4209589), | |
vec2(-0.3296949, -0.2300484), | |
vec2(-0.7646635, -0.5015364), | |
vec2(-0.8680285, -0.1527984), | |
vec2(-0.04608675, 0.1312256), | |
vec2(-0.428542, 0.06557278), | |
vec2(0.3862999, 0.1360214), | |
vec2(0.9446273, 0.1907608), | |
vec2(0.767735, 0.4751784), | |
vec2(0.00614462, 0.4327521), | |
vec2(0.4892556, 0.4249187), | |
vec2(-0.8814729, 0.2260128), | |
vec2(-0.5271859, 0.3801891), | |
vec2(-0.6847409, 0.680231), | |
vec2(-0.4495289, 0.8691995), | |
vec2(-0.3142174, 0.5816193), | |
vec2(0.668636, 0.1689468), | |
vec2(0.03808001, 0.7051221), | |
vec2(0.3598493, 0.7828714), | |
vec2(-0.09508449, 0.9845307) | |
); | |
*/ | |
// Alternative Poisson Disks | |
/* | |
int poissonDiskCount = 81; | |
vec2 poissonDisk[81] = vec2[] | |
( | |
vec2(-0.3699564, -0.8923714), | |
vec2(-0.2991857, -0.7419077), | |
vec2(-0.4836373, -0.7128996), | |
vec2(-0.4001464, -0.5349672), | |
vec2(-0.1919933, -0.08249668), | |
vec2(-0.01000632, -0.1949988), | |
vec2(0.01308492, -0.3854378), | |
vec2(0.2060275, -0.6136295), | |
vec2(0.4246204, -0.5385646), | |
vec2(0.5739859, -0.6241939), | |
vec2(0.7209898, -0.4848168), | |
vec2(0.9162411, -0.3304724), | |
vec2(0.9904354, -0.09592855), | |
vec2(0.8480595, -0.00145522), | |
vec2(0.8411906, -0.1628317), | |
vec2(0.7471918, -0.3052474), | |
vec2(0.6039378, -0.1701832), | |
vec2(0.4796014, -0.323362), | |
vec2(0.2568311, -0.3751998), | |
vec2(0.183625, -0.2148832), | |
vec2(0.3433107, -0.1401113), | |
vec2(0.4316378, 0.03481985), | |
vec2(0.3968316, 0.1936454), | |
vec2(0.4381528, 0.3894764), | |
vec2(0.2114601, 0.4048975), | |
vec2(0.1994308, 0.2444916), | |
vec2(0.1721712, 0.01987821), | |
vec2(0, 0), | |
vec2(0.00648162, 0.1718858), | |
vec2(0.0371051, 0.3398669), | |
vec2(-0.00288106, 0.5080842), | |
vec2(-0.101272, 0.657119), | |
vec2(-0.2265163, 0.8383843), | |
vec2(-0.3772848, 0.9089825), | |
vec2(-0.5570081, 0.7581005), | |
vec2(-0.6944108, 0.6688873), | |
vec2(-0.811931, 0.5597007), | |
vec2(-0.8990598, 0.397422), | |
vec2(-0.7313915, 0.3527614), | |
vec2(-0.5909905, 0.2295826), | |
vec2(-0.4016944, 0.2946137), | |
vec2(-0.4303952, 0.1000971), | |
vec2(-0.2593866, 0.1194347), | |
vec2(-0.1583612, 0.2668041), | |
vec2(-0.2674951, 0.5013697), | |
vec2(-0.4031608, 0.664479), | |
vec2(-0.5372077, 0.5246259), | |
vec2(-0.880586, 0.1983642), | |
vec2(-0.7635881, 0.034782), | |
vec2(-0.8213844, -0.1374991), | |
vec2(-0.9844468, -0.07959031), | |
vec2(-0.9553765, -0.2592497), | |
vec2(-0.8055727, -0.3689174), | |
vec2(-0.7207122, -0.5792082), | |
vec2(-0.5762517, -0.4557166), | |
vec2(-0.5893056, -0.294492), | |
vec2(-0.6413326, -0.1379207), | |
vec2(-0.4876427, -0.06701604), | |
vec2(-0.3812391, -0.228707), | |
vec2(-0.2002228, -0.3431383), | |
vec2(-0.238193, -0.5032565), | |
vec2(-0.1105472, -0.6067951), | |
vec2(-0.1185818, -0.829915), | |
vec2(0.04267518, -0.7710204), | |
vec2(0.2299606, -0.8834579), | |
vec2(0.3829597, -0.8357664), | |
vec2(0.5988549, -0.796147), | |
vec2(0.6401687, 0.05738575), | |
vec2(0.6434335, 0.2378507), | |
vec2(0.7821028, 0.3695812), | |
vec2(0.9417133, 0.3353129), | |
vec2(0.843325, 0.1718658), | |
vec2(0.6487916, 0.5051771), | |
vec2(0.7990769, 0.5808157), | |
vec2(0.6465626, 0.7169496), | |
vec2(0.4615826, 0.6353213), | |
vec2(0.389738, 0.8312076), | |
vec2(0.2560864, 0.944613), | |
vec2(0.0979304, 0.8286165), | |
vec2(-0.06759234, 0.9140676), | |
vec2(0.1950012, 0.647736) | |
); | |
*/ | |
/* | |
int poissonDiskCount = 49; | |
vec2 poissonDisk[49] =vec2[] | |
( | |
vec2(0, 0), | |
vec2(0.2704636, -0.109632), | |
vec2(-0.1407196, -0.2135445), | |
vec2(0.1835398, 0.1544003), | |
vec2(-0.3016819, 0.02295322), | |
vec2(-0.1511358, 0.2107215), | |
vec2(0.5261667, 0.1747418), | |
vec2(0.106212, -0.4557395), | |
vec2(0.4724373, -0.4680161), | |
vec2(0.07686187, -0.1986526), | |
vec2(0.5025072, -0.1166459), | |
vec2(0.06726067, 0.5551263), | |
vec2(0.2961665, 0.4554047), | |
vec2(0.4371642, -0.6975633), | |
vec2(0.7450042, -0.6084697), | |
vec2(0.7879587, -0.3145762), | |
vec2(0.853178, -0.09371731), | |
vec2(0.3479224, -0.9342913), | |
vec2(0.2962557, -0.3351233), | |
vec2(0.1291568, -0.9127867), | |
vec2(0.1676721, -0.6902292), | |
vec2(-0.2335626, -0.5687734), | |
vec2(-0.1351299, -0.9101442), | |
vec2(-0.261507, 0.4907885), | |
vec2(0.2484025, 0.9168846), | |
vec2(0.4132242, 0.6466962), | |
vec2(-0.06851456, 0.7667027), | |
vec2(-0.4992727, -0.2029795), | |
vec2(-0.7559373, -0.4068739), | |
vec2(-0.4855339, 0.1969039), | |
vec2(-0.7640306, -0.1964805), | |
vec2(-0.5730085, -0.6135933), | |
vec2(-0.8484348, -0.00299876), | |
vec2(-0.4140792, 0.8315768), | |
vec2(-0.485181, 0.5305088), | |
vec2(0.6689701, 0.5768808), | |
vec2(0.05106151, 0.3191291), | |
vec2(0.5435089, 0.3871753), | |
vec2(0.7201117, 0.07126629), | |
vec2(-0.627667, -0.00750978), | |
vec2(-0.7517983, 0.3829239), | |
vec2(-0.9550468, 0.2630464), | |
vec2(-0.9520001, -0.2915859), | |
vec2(-0.3590643, -0.8519062), | |
vec2(-0.7153674, 0.6039236), | |
vec2(-0.441388, -0.4258223), | |
vec2(-0.0022588, 0.9828641), | |
vec2(0.7638181, 0.3658235), | |
vec2(0.9487044, 0.1562798) | |
); | |
//*/ | |
///* | |
int poissonDiskCount = 49; | |
vec2 poissonDisk[49] = vec2[] | |
( | |
vec2(0.3180534, 0.4481016), | |
vec2(0.2678761, 0.0108069), | |
vec2(0.4059432, -0.1698658), | |
vec2(0.2166998, -0.2913965), | |
vec2(0.5095147, -0.7720755), | |
vec2(0.6903954, -0.6289557), | |
vec2(0.5788592, -0.444398), | |
vec2(0.3652714, -0.4735996), | |
vec2(0.06218402, -0.5944019), | |
vec2(0.2022222, -0.8094499), | |
vec2(-0.05008334, -0.8284965), | |
vec2(-0.276035, -0.7895288), | |
vec2(-0.4997773, -0.8038069), | |
vec2(-0.654102, -0.6489612), | |
vec2(-0.8112803, -0.4295334), | |
vec2(-0.594835, -0.3155343), | |
vec2(-0.4238591, -0.4459266), | |
vec2(-0.2346791, -0.5664694), | |
vec2(-0.0837327, -0.3297902), | |
vec2(-0.315086, -0.2049854), | |
vec2(-0.2446316, 0.0475988), | |
vec2(0, 0), | |
vec2(-0.05167853, 0.2587596), | |
vec2(0.1658537, 0.2365123), | |
vec2(0.08676389, 0.4655274), | |
vec2(0.00613963, 0.6610284), | |
vec2(-0.1701808, 0.7868701), | |
vec2(-0.3171133, 0.9444721), | |
vec2(-0.531477, 0.7083178), | |
vec2(-0.7212166, 0.5538531), | |
vec2(-0.7275055, 0.3375536), | |
vec2(-0.9388103, 0.2060823), | |
vec2(-0.9737488, -0.00821011), | |
vec2(-0.8841391, -0.2061071), | |
vec2(-0.5946057, 0.0165981), | |
vec2(-0.4465454, 0.3816047), | |
vec2(-0.2054298, 0.5647205), | |
vec2(0.01520541, 0.9229794), | |
vec2(0.2149482, 0.7891803), | |
vec2(0.4386395, 0.8156134), | |
vec2(0.585341, 0.6536921), | |
vec2(0.599094, 0.4178026), | |
vec2(0.4628473, 0.2398231), | |
vec2(0.6354845, 0.08313083), | |
vec2(0.6402243, -0.1312514), | |
vec2(0.8978871, -0.3225123), | |
vec2(0.9632866, -0.1101094), | |
vec2(0.8624113, 0.1889227), | |
vec2(0.8072352, 0.5132092) | |
); | |
//*/ | |
/* | |
int poissonDiskCount = 25; | |
vec2 poissonDisk[25] = vec2[] | |
( | |
vec2(0.513658, -0.361747), | |
vec2(0.7941055, -0.5156633), | |
vec2(0.4015315, 0.00368995), | |
vec2(0.2348373, -0.5646414), | |
vec2(0.08148332, -0.1521704), | |
vec2(0.9071004, -0.04301345), | |
vec2(0.5765684, -0.7820904), | |
vec2(0.02575831, -0.9248317), | |
vec2(-0.4247141, -0.7601865), | |
vec2(-0.1650984, -0.5609509), | |
vec2(-0.00553054, 0.4322597), | |
vec2(0.374622, 0.536724), | |
vec2(0.629549, 0.3171313), | |
vec2(-0.1453903, 0.8028749), | |
vec2(0.1050673, 0.9782572), | |
vec2(0.7705216, 0.6211317), | |
vec2(-0.5209134, -0.2073833), | |
vec2(-0.2157063, -0.05150497), | |
vec2(-0.7314271, -0.4448851), | |
vec2(-0.9658175, -0.08176702), | |
vec2(-0.6456084, 0.08727718), | |
vec2(0.4758473, 0.8578165), | |
vec2(-0.4970213, 0.3748735), | |
vec2(-0.79823, 0.4584326), | |
vec2(-0.4652869, 0.7911729) | |
); | |
*/ | |
/* | |
int poissonDiskCount = 121; | |
vec2 poissonDisk[121] = vec2[] | |
( | |
vec2(-0.8145391, 0.2018038), | |
vec2(-0.7680936, 0.01102507), | |
vec2(-0.8179, 0.4190474), | |
vec2(-0.6272386, 0.3042867), | |
vec2(-0.6388035, 0.09087871), | |
vec2(-0.973397, 0.09434819), | |
vec2(-0.9286931, 0.3049383), | |
vec2(-0.9437586, -0.0878182), | |
vec2(-0.6478248, 0.5386735), | |
vec2(-0.6696737, -0.1069194), | |
vec2(-0.5030807, -0.04799687), | |
vec2(-0.4554624, 0.1801287), | |
vec2(-0.4744284, 0.3629912), | |
vec2(-0.6091245, 0.709008), | |
vec2(-0.4431208, 0.6060795), | |
vec2(-0.4783991, 0.872493), | |
vec2(-0.7650282, 0.6261441), | |
vec2(-0.648209, -0.2541103), | |
vec2(-0.4782754, -0.1895011), | |
vec2(-0.8420978, -0.2915789), | |
vec2(-0.3320211, 0.4459547), | |
vec2(-0.2184307, 0.3102135), | |
vec2(-0.5249589, -0.3567855), | |
vec2(-0.6339359, -0.4816926), | |
vec2(-0.7745628, -0.4331442), | |
vec2(-0.2853205, 0.6266201), | |
vec2(-0.3126772, 0.2082842), | |
vec2(-0.2888178, -0.1057123), | |
vec2(-0.3040508, 0.07155678), | |
vec2(-0.1689375, 0.00208978), | |
vec2(-0.1276036, -0.230842), | |
vec2(-0.2645069, -0.251865), | |
vec2(-0.05814912, -0.07507057), | |
vec2(-0.96618, -0.2335756), | |
vec2(-0.3181189, 0.9354967), | |
vec2(-0.279675, 0.8050285), | |
vec2(0.0285327, 0.0285488), | |
vec2(0.05076085, -0.2321206), | |
vec2(-0.04266489, 0.1599286), | |
vec2(-0.1801453, 0.1479051), | |
vec2(-0.7665108, -0.6125543), | |
vec2(-0.5986278, -0.633567), | |
vec2(-0.3869458, -0.5376865), | |
vec2(-0.1019354, 0.6640193), | |
vec2(-0.1567075, 0.4577439), | |
vec2(0.0997559, 0.523626), | |
vec2(0.08452818, 0.33801), | |
vec2(-0.0771656, 0.3348197), | |
vec2(-0.2743955, -0.4123585), | |
vec2(-0.1417506, -0.3780532), | |
vec2(0.06017977, -0.3908472), | |
vec2(0.1209376, 0.1767513), | |
vec2(0.2930699, 0.1947938), | |
vec2(0.2726678, 0.4499197), | |
vec2(0.3479996, 0.3333567), | |
vec2(-0.3884761, -0.3228932), | |
vec2(-0.4060122, -0.7620402), | |
vec2(-0.2692429, -0.6134833), | |
vec2(-0.2350422, -0.751938), | |
vec2(0.2291963, -0.5089285), | |
vec2(-0.1423385, -0.5567046), | |
vec2(0.2624367, -0.3772998), | |
vec2(0.1845447, -0.1553576), | |
vec2(0.03282839, -0.552046), | |
vec2(-0.03120033, 0.7981148), | |
vec2(-0.09216484, -0.7041956), | |
vec2(0.05856795, -0.7267763), | |
vec2(0.06613369, -0.9221421), | |
vec2(-0.1888615, -0.9536768), | |
vec2(-0.07146626, -0.8623131), | |
vec2(0.1756456, -0.01950932), | |
vec2(0.193867, -0.8533896), | |
vec2(0.4005747, -0.10389), | |
vec2(0.3240081, 0.04697539), | |
vec2(0.492248, 0.0242701), | |
vec2(0.5220208, 0.1560711), | |
vec2(0.411791, -0.8235737), | |
vec2(0.2914644, -0.9484619), | |
vec2(0.237363, -0.6849211), | |
vec2(0.4828349, 0.4181724), | |
vec2(0.2241743, 0.6966354), | |
vec2(0.3593884, 0.6664988), | |
vec2(-0.6096635, -0.7725464), | |
vec2(-0.3624007, -0.9301076), | |
vec2(-0.1511986, 0.9812689), | |
vec2(0.1316039, 0.9200104), | |
vec2(0.04489716, 0.6663558), | |
vec2(0.4192846, 0.8968149), | |
vec2(0.5136389, 0.5955158), | |
vec2(0.5978712, 0.714323), | |
vec2(0.2909992, 0.8463242), | |
vec2(0.667025, 0.2393008), | |
vec2(0.6945911, 0.5848529), | |
vec2(0.6720968, 0.4026787), | |
vec2(0.4061505, -0.3091075), | |
vec2(-0.00606923, 0.9408461), | |
vec2(0.6880797, -0.09980167), | |
vec2(0.6449918, 0.08029267), | |
vec2(0.5474248, -0.2456431), | |
vec2(0.5469157, -0.103126), | |
vec2(0.8124132, 0.2098381), | |
vec2(0.8384665, 0.5237998), | |
vec2(0.8843539, 0.3321715), | |
vec2(0.8657284, 0.06668415), | |
vec2(0.4219247, -0.5008652), | |
vec2(0.3702411, -0.6292241), | |
vec2(0.8320472, -0.09420462), | |
vec2(0.9697028, 0.1705226), | |
vec2(0.9808273, -0.08202744), | |
vec2(0.5489869, -0.4111728), | |
vec2(0.7044868, -0.3709804), | |
vec2(-0.04647561, 0.5369669), | |
vec2(0.7663563, -0.53933), | |
vec2(0.6115797, -0.5505605), | |
vec2(0.7589383, -0.24584), | |
vec2(0.9354028, -0.2223959), | |
vec2(0.5466368, -0.681439), | |
vec2(0.1172148, 0.780805), | |
vec2(0.9163168, -0.3768335), | |
vec2(0.6836037, -0.6895471), | |
vec2(0.3884423, 0.5294771) | |
); | |
*/ | |
/*int poissonDiskCount = 192; | |
vec2 poissonDisk[192] = vec2[] | |
( | |
vec2(0, 0), | |
vec2(-0.1579779, -0.00667168), | |
vec2(-0.04788195, 0.148602), | |
vec2(0.1551555, -0.01143336), | |
vec2(0.150933, 0.1006983), | |
vec2(-0.101286, -0.1247007), | |
vec2(0.06778635, -0.1162965), | |
vec2(0.01246635, -0.2127644), | |
vec2(-0.1716932, 0.1150915), | |
vec2(0.08373228, 0.1994599), | |
vec2(0.1782644, -0.1263033), | |
vec2(0.1765209, -0.2706989), | |
vec2(0.3171727, -0.09914725), | |
vec2(0.2813143, 0.05613242), | |
vec2(0.3776773, -0.1993745), | |
vec2(0.2817168, -0.3165311), | |
vec2(0.02159015, -0.3842939), | |
vec2(-0.1786465, -0.2897428), | |
vec2(0.1391767, -0.3828608), | |
vec2(-0.2790399, -0.1496314), | |
vec2(-0.2771961, -0.03004173), | |
vec2(-0.3129101, 0.1163882), | |
vec2(-0.40106, 0.02569774), | |
vec2(-0.4880563, -0.05920667), | |
vec2(-0.3856499, -0.2196232), | |
vec2(-0.386703, -0.1052163), | |
vec2(-0.3146591, -0.3202933), | |
vec2(0.2762218, 0.2582802), | |
vec2(0.156653, 0.2991701), | |
vec2(0.3450646, 0.1589701), | |
vec2(0.4776564, -0.2509807), | |
vec2(0.4475874, -0.0646226), | |
vec2(0.3522668, -0.4110779), | |
vec2(0.5725766, -0.1784626), | |
vec2(0.4925709, -0.366239), | |
vec2(-0.1415097, -0.4227809), | |
vec2(-0.3487023, -0.427642), | |
vec2(-0.2392384, -0.4874585), | |
vec2(-0.06632553, -0.2968008), | |
vec2(-0.269476, -0.5939365), | |
vec2(-0.0466212, -0.5433949), | |
vec2(-0.1583137, -0.6402723), | |
vec2(0.06257112, -0.5023946), | |
vec2(-0.3823169, -0.5661208), | |
vec2(-0.3472781, -0.6770487), | |
vec2(0.4223058, 0.05091112), | |
vec2(0.4668685, 0.1556292), | |
vec2(0.5667015, -0.05944833), | |
vec2(0.6173584, 0.06814981), | |
vec2(0.5836416, 0.1949372), | |
vec2(0.4099706, 0.2548642), | |
vec2(-0.575941, -0.2072039), | |
vec2(-0.494781, -0.2899517), | |
vec2(-0.5007762, -0.4052824), | |
vec2(-0.6112139, -0.3322126), | |
vec2(-0.6244487, -0.06556911), | |
vec2(-0.7736475, -0.2936879), | |
vec2(-0.6923394, -0.2186789), | |
vec2(-0.7487834, -0.1236023), | |
vec2(-0.5031706, -0.519168), | |
vec2(-0.2523997, -0.8048553), | |
vec2(-0.3718923, -0.8122362), | |
vec2(-0.5324536, -0.6347923), | |
vec2(-0.5043494, -0.7611477), | |
vec2(-0.6982023, -0.5230556), | |
vec2(-0.6039793, -0.464543), | |
vec2(-0.7892492, -0.4587003), | |
vec2(-0.05500655, -0.7723967), | |
vec2(-0.2324222, -0.9531521), | |
vec2(-0.3424152, -0.936919), | |
vec2(-0.1380014, -0.8790072), | |
vec2(-0.6583214, -0.751954), | |
vec2(-0.4789731, -0.8761995), | |
vec2(0.7079763, 0.1936365), | |
vec2(0.579138, 0.3485152), | |
vec2(0.4671302, 0.3769446), | |
vec2(0.7468429, 0.06134389), | |
vec2(0.690945, 0.3690235), | |
vec2(0.4938911, -0.5367124), | |
vec2(0.629364, -0.368711), | |
vec2(0.6044188, -0.5526005), | |
vec2(0.691502, -0.2767167), | |
vec2(0.2958276, 0.4457444), | |
vec2(0.1484887, 0.4106334), | |
vec2(0.04267848, -0.6358007), | |
vec2(-0.0121838, -0.9025026), | |
vec2(0.06259318, -0.7993793), | |
vec2(0.02864453, 0.3368952), | |
vec2(-0.1411658, 0.2831758), | |
vec2(-0.256573, 0.2148015), | |
vec2(-0.8890084, -0.1475827), | |
vec2(-0.8996029, -0.2684086), | |
vec2(-0.7514127, -0.00754975), | |
vec2(-0.9030489, -0.4151296), | |
vec2(0.7472506, 0.5188246), | |
vec2(0.8034367, 0.2866946), | |
vec2(0.8913394, 0.4029096), | |
vec2(0.5173027, 0.4913935), | |
vec2(0.6376375, 0.4687352), | |
vec2(0.6764172, -0.7140666), | |
vec2(0.5328749, -0.6922466), | |
vec2(0.7179219, -0.5360914), | |
vec2(0.7633882, -0.4209933), | |
vec2(0.4024372, -0.6148348), | |
vec2(0.8598717, 0.1613377), | |
vec2(0.9158563, 0.2617805), | |
vec2(0.02880715, 0.4651046), | |
vec2(-0.8024176, -0.5708051), | |
vec2(0.4036525, 0.4791513), | |
vec2(-0.5743513, 0.06212753), | |
vec2(-0.4342578, 0.1386052), | |
vec2(-0.6539742, -0.6404192), | |
vec2(-0.9409897, -0.00469393), | |
vec2(-0.7622019, 0.19778), | |
vec2(-0.6463298, 0.1851418), | |
vec2(-0.8436922, 0.1103997), | |
vec2(0.8063032, -0.2633983), | |
vec2(0.721742, -0.1694097), | |
vec2(0.7971572, -0.08403494), | |
vec2(0.873913, -0.3760379), | |
vec2(0.8907289, -0.1855821), | |
vec2(-0.2572967, 0.4102247), | |
vec2(-0.3428998, 0.3251416), | |
vec2(-0.4671071, 0.2753691), | |
vec2(0.9015735, 0.05007015), | |
vec2(0.676307, -0.03709444), | |
vec2(0.2869727, -0.5194738), | |
vec2(0.369273, -0.8051155), | |
vec2(0.2711763, -0.6720726), | |
vec2(0.1196353, -0.9074619), | |
vec2(0.2508053, -0.8040956), | |
vec2(0.1533686, -0.7228661), | |
vec2(0.230132, -0.9219093), | |
vec2(0.5014529, 0.6222036), | |
vec2(0.6576515, 0.6356055), | |
vec2(0.3635858, 0.616609), | |
vec2(0.3830075, 0.7811894), | |
vec2(0.5275519, 0.7454325), | |
vec2(0.2079661, 0.5123486), | |
vec2(0.0659195, 0.5952332), | |
vec2(-0.4025973, 0.5679626), | |
vec2(-0.1505939, 0.5776492), | |
vec2(-0.2635109, 0.5880249), | |
vec2(-0.1467772, 0.412355), | |
vec2(-0.464153, 0.4041325), | |
vec2(-0.3643259, 0.4554945), | |
vec2(-0.5800178, 0.2742772), | |
vec2(-0.7319973, 0.3212687), | |
vec2(-0.5879882, 0.3921616), | |
vec2(0.7585585, -0.6402012), | |
vec2(0.983243, -0.1255625), | |
vec2(0.8562369, -0.5134028), | |
vec2(-0.9444854, 0.1756041), | |
vec2(-0.8864825, 0.2776531), | |
vec2(-0.8555552, 0.3901908), | |
vec2(-0.09679115, -0.991565), | |
vec2(0.4941317, -0.7995735), | |
vec2(0.9752547, 0.1504787), | |
vec2(0.2535152, 0.6380891), | |
vec2(0.3527091, 0.3497678), | |
vec2(-0.5381499, 0.4952551), | |
vec2(-0.509964, 0.6199554), | |
vec2(-0.5670242, 0.7776898), | |
vec2(-0.6675494, 0.5049722), | |
vec2(-0.4056781, 0.6934279), | |
vec2(-0.4296919, 0.8203589), | |
vec2(-0.6908807, 0.6481661), | |
vec2(0.152851, -0.6095042), | |
vec2(0.9947274, -0.01071189), | |
vec2(0.1782838, -0.4899755), | |
vec2(0.1892615, 0.8112504), | |
vec2(0.3213653, 0.8830229), | |
vec2(0.4490296, 0.8808565), | |
vec2(0.2154352, 0.918152), | |
vec2(-0.3044533, 0.7643533), | |
vec2(0.00174637, 0.8900059), | |
vec2(0.1551054, 0.7052948), | |
vec2(0.00232656, 0.7674119), | |
vec2(0.1045302, 0.9482439), | |
vec2(-0.04334186, 0.6205565), | |
vec2(-0.120597, 0.8939695), | |
vec2(-0.1102617, 0.7526636), | |
vec2(-0.05782435, 0.9935969), | |
vec2(-0.1942069, 0.9803006), | |
vec2(-0.7789822, 0.4745164), | |
vec2(-0.2393045, 0.8783966), | |
vec2(-0.207745, 0.6903685), | |
vec2(-0.3565365, 0.9071383), | |
vec2(0.9501814, -0.285571), | |
vec2(0.4327048, -0.8951513), | |
vec2(-0.7105811, 0.09468219), | |
vec2(-0.7969888, 0.5896265) | |
);*/ | |
// Use default shadows in particles - h/t Hata's Shader Toggle | |
bool particleOptimization = false; | |
// Fog; enable for somewhat more realistic fog falloff | |
bool fancyFog = true; | |
// modify the sin curve power | |
float fogExponent = 1.0f; | |
// Superglow - Off-like glow effect h/t Pah1023 (https://forum.blockland.us/index.php?topic=316738.msg9781138#msg9781138) | |
bool superGlow = true; | |
// Specular Power - control the size of the specular highlight; larger values = smaller specular highlight | |
float specularPower = 12.0f; | |
// Adjust the brightness of the specular effect | |
float dirLightSpecularMultiplier = 0.5f; | |
// 0 - Normal, 1 - Shadows, 2 - Position, 3 - Normals, 4 - Albedo, 5 - reflectVec, 6 - viewDelta, 7 - vPos, 8 - texCoord | |
int debugDisplayMode = 0; | |
// End of tweaking variables | |
// Varying. | |
varying vec4 vPos; | |
varying vec3 worldNormal; | |
varying vec3 worldPos; | |
// Global directional light uniforms. | |
uniform vec4 dirLightDir; | |
uniform vec4 dirLightColor; | |
uniform vec4 dirLightAmbient; | |
uniform vec4 dirShadowColor; | |
// Misc uniforms. | |
uniform vec3 camPos; | |
uniform mat4 obj2World; | |
uniform mat4 world2Cam; | |
uniform int isParticle; | |
uniform int doColorMultiply; | |
uniform int glow; | |
uniform sampler2DArray stex; | |
uniform sampler2D tex; | |
// Surface calculations, including specular power. | |
varying vec2 texCoord; | |
vec4 viewDelta; | |
float specular; | |
float NdotL; | |
vec3 reflectVec; | |
void calculateSurface(vec4 color, inout vec4 albedo) | |
{ | |
viewDelta.xyz = worldPos - camPos; | |
viewDelta.w = length(viewDelta.xyz); | |
viewDelta.xyz = -normalize(viewDelta.xyz); | |
vec4 texAlbedo = texture2D(tex, texCoord); | |
albedo.rgb = mix(color.rgb, texAlbedo.rgb, texAlbedo.a); | |
if(doColorMultiply == 1) | |
albedo *= gl_Color; | |
albedo.a = color.a; | |
NdotL = max(dot(worldNormal, dirLightDir.xyz), 0.0f); | |
reflectVec = normalize(reflect(-dirLightDir.xyz, worldNormal)); | |
specular = pow(max(dot(reflectVec, viewDelta.xyz), 0.0f), specularPower) * length(texAlbedo.rgb); // change this to change the size of the sun specular reflection | |
// Uncomment below for a neat rainbow color effect on everything | |
// albedo.rgb = normalize(viewDelta.xyz); | |
} | |
// Fogging. | |
uniform vec4 fogBaseColor; | |
uniform vec4 fogConsts; | |
uniform sampler2D fogTex; | |
varying vec2 fogCoords; | |
void applyFog(inout vec4 albedo, in float occlusionFactor) | |
{ | |
// Calculate fog. | |
vec4 fogColor = texture2D(fogTex, fogCoords) * fogBaseColor; | |
// Blend it. | |
if (fancyFog) | |
albedo = mix(albedo, fogColor, pow((0.5f + 1.0f / 2.0f * sin(fogColor.a * 3.141592654f - 1.570796327f)), fogExponent)); | |
else | |
albedo = mix(albedo, fogColor, fogColor.a); | |
} | |
// Shadowing | |
uniform vec4 far_d; | |
uniform vec2 texSize; // x - size, y - 1/size | |
uniform vec4 zScale; | |
uniform int shadowSplitCount; | |
void calculateShadowCoords(inout vec4 shadow_coordA, inout vec4 shadow_coordB, out float blend) | |
{ | |
int index = 3; | |
float fudgeFactorA = 0.0f; | |
float fudgeFactorB = 0.0f; | |
fudgeFactorA = fudgeFactor4 / zScale.w; | |
fudgeFactorB = fudgeFactor4 / zScale.w; | |
blend = 0.0f; | |
// find the appropriate depth map to look up in based on the depth of this fragment | |
if(vPos.y < far_d.x) | |
{ | |
index = 0; | |
if(shadowSplitCount > 1) | |
blend = clamp( (vPos.y - (far_d.x * blendAlpha)) / (far_d.x * blendBeta), 0.0f, 1.0f); | |
fudgeFactorA = fudgeFactor1 / zScale.x; | |
fudgeFactorB = fudgeFactor2 / zScale.y; | |
} | |
else if(vPos.y < far_d.y) | |
{ | |
index = 1; | |
if(shadowSplitCount > 2) | |
blend = clamp( (vPos.y - (far_d.y * blendAlpha)) / (far_d.x * blendBeta), 0.0f, 1.0f); | |
fudgeFactorA = fudgeFactor2 / zScale.y; | |
fudgeFactorB = fudgeFactor3 / zScale.z; | |
} | |
else if(vPos.y < far_d.z) | |
{ | |
index = 2; | |
if(shadowSplitCount > 3) | |
blend = clamp( (vPos.y - (far_d.z * blendAlpha)) / (far_d.x * blendBeta), 0.0f, 1.0f); | |
fudgeFactorA = fudgeFactor3 / zScale.z; | |
fudgeFactorB = fudgeFactor4 / zScale.w; | |
} | |
// transform this fragment's position from view space to scaled light clip space | |
// such that the xy coordinates are in [0;1] | |
// note there is no need to divide by w for orthogonal light sources | |
shadow_coordA = gl_TextureMatrix[index] * vPos; | |
if (dynamicFF) | |
{ | |
shadow_coordA.w = shadow_coordA.z - max(dynamicFudgeFactor * fudgeFactorA * (1.0 - dot(worldNormal, dirLightDir.xyz)), fudgeFactorA); // Figure the input coordinate for PCF sampling if appropriate. | |
} | |
else | |
{ | |
shadow_coordA.w = shadow_coordA.z - fudgeFactorA; // Figure the input coordinate for PCF sampling if appropriate. | |
} | |
shadow_coordA.z = float(index); // Encode the layer to sample. | |
//don't have to set second shadow coord if we're not blending | |
if(blend > 0.0f) | |
{ | |
shadow_coordB = gl_TextureMatrix[index + 1] * vPos; | |
if (dynamicFF) | |
{ | |
shadow_coordB.w = shadow_coordB.z - max(dynamicFudgeFactor * fudgeFactorB * (1.0 - dot(worldNormal, dirLightDir.xyz)), fudgeFactorB); | |
} | |
else | |
{ | |
shadow_coordB.w = shadow_coordB.z - fudgeFactorB; | |
} | |
shadow_coordB.z = float(index + 1); | |
} | |
} | |
// Point lighting | |
uniform vec4 pointLightPos0; | |
uniform vec4 pointLightColor0; | |
uniform float pointLightRadius0; | |
uniform vec4 pointLightPos1; | |
uniform vec4 pointLightColor1; | |
uniform float pointLightRadius1; | |
uniform vec4 pointLightPos2; | |
uniform vec4 pointLightColor2; | |
uniform float pointLightRadius2; | |
uniform vec4 pointLightPos3; | |
uniform vec4 pointLightColor3; | |
uniform float pointLightRadius3; | |
uniform vec4 pointLightPos4; | |
uniform vec4 pointLightColor4; | |
uniform float pointLightRadius4; | |
uniform vec4 pointLightPos5; | |
uniform vec4 pointLightColor5; | |
uniform float pointLightRadius5; | |
uniform vec4 pointLightPos6; | |
uniform vec4 pointLightColor6; | |
uniform float pointLightRadius6; | |
uniform vec4 pointLightPos7; | |
uniform vec4 pointLightColor7; | |
uniform float pointLightRadius7; | |
vec4 accumulatePointLights() | |
{ | |
vec4 pointLightTotal = vec4(0.0f, 0.0f, 0.0f, 0.0f); | |
vec3 lightDelta = vec3(0.0f, 0.0f, 0.0f); | |
float lightDot = 0.0f; | |
float ratio = 0.0f; | |
// Calculate effects of the 8 point lights. | |
lightDelta = worldPos.xyz - pointLightPos0.xyz; | |
lightDot = max(dot(-normalize(lightDelta), worldNormal), 0.0f); | |
ratio = 1.0f - (length(lightDelta) / pointLightRadius0); | |
ratio = ratio * ratio * ratio * 0.4f; | |
ratio = max(ratio, 0.0f); | |
pointLightTotal.xyz += ratio * lightDot * pointLightColor0.xyz; | |
lightDelta = worldPos.xyz - pointLightPos1.xyz; | |
lightDot = max(dot(-normalize(lightDelta), worldNormal), 0.0f); | |
ratio = 1.0f - (length(lightDelta) / pointLightRadius1); | |
ratio = ratio * ratio * ratio * 0.4f; | |
ratio = max(ratio, 0.0f); | |
pointLightTotal.xyz += ratio * lightDot * pointLightColor1.xyz; | |
lightDelta = worldPos.xyz - pointLightPos2.xyz; | |
lightDot = max(dot(-normalize(lightDelta), worldNormal), 0.0f); | |
ratio = 1.0f - (length(lightDelta) / pointLightRadius2); | |
ratio = ratio * ratio * ratio * 0.4f; | |
ratio = max(ratio, 0.0f); | |
pointLightTotal.xyz += ratio * lightDot * pointLightColor2.xyz; | |
lightDelta = worldPos.xyz - pointLightPos3.xyz; | |
lightDot = max(dot(-normalize(lightDelta), worldNormal), 0.0f); | |
ratio = 1.0f - (length(lightDelta) / pointLightRadius3); | |
ratio = ratio * ratio * ratio * 0.4f; | |
ratio = max(ratio, 0.0f); | |
pointLightTotal.xyz += ratio * lightDot * pointLightColor3.xyz; | |
lightDelta = worldPos.xyz - pointLightPos4.xyz; | |
lightDot = max(dot(-normalize(lightDelta), worldNormal), 0.0f); | |
ratio = 1.0f - (length(lightDelta) / pointLightRadius4); | |
ratio = ratio * ratio * ratio * 0.4f; | |
ratio = max(ratio, 0.0f); | |
pointLightTotal.xyz += ratio * lightDot * pointLightColor4.xyz; | |
lightDelta = worldPos.xyz - pointLightPos5.xyz; | |
lightDot = max(dot(-normalize(lightDelta), worldNormal), 0.0f); | |
ratio = 1.0f - (length(lightDelta) / pointLightRadius5); | |
ratio = ratio * ratio * ratio * 0.4f; | |
ratio = max(ratio, 0.0f); | |
pointLightTotal.xyz += ratio * lightDot * pointLightColor5.xyz; | |
lightDelta = worldPos.xyz - pointLightPos6.xyz; | |
lightDot = max(dot(-normalize(lightDelta), worldNormal), 0.0f); | |
ratio = 1.0f - (length(lightDelta) / pointLightRadius6); | |
ratio = ratio * ratio * ratio * 0.4f; | |
ratio = max(ratio, 0.0f); | |
pointLightTotal.xyz += ratio * lightDot * pointLightColor6.xyz; | |
lightDelta = worldPos.xyz - pointLightPos7.xyz; | |
lightDot = max(dot(-normalize(lightDelta), worldNormal), 0.0f); | |
ratio = 1.0f - (length(lightDelta) / pointLightRadius7); | |
ratio = ratio * ratio * ratio * 0.4f; | |
ratio = max(ratio, 0.0f); | |
pointLightTotal.xyz += ratio * lightDot * pointLightColor7.xyz; | |
return pointLightTotal; | |
} | |
vec4 accumulateParticlePointLights() | |
{ | |
vec4 pointLightTotal = vec4(0.0f, 0.0f, 0.0f, 0.0f); | |
vec3 lightDelta = vec3(0.0f, 0.0f, 0.0f); | |
float ratio = 0.0f; | |
// Calculate effects of the 8 point lights. | |
lightDelta = worldPos.xyz - pointLightPos0.xyz; | |
ratio = 1.0f - (length(lightDelta) / pointLightRadius0); | |
ratio = ratio * ratio * ratio * 0.4f; | |
ratio = max(ratio, 0.0f); | |
pointLightTotal.xyz += ratio * pointLightColor0.xyz; | |
lightDelta = worldPos.xyz - pointLightPos1.xyz; | |
ratio = 1.0f - (length(lightDelta) / pointLightRadius1); | |
ratio = ratio * ratio * ratio * 0.4f; | |
ratio = max(ratio, 0.0f); | |
pointLightTotal.xyz += ratio * pointLightColor1.xyz; | |
return pointLightTotal; | |
} | |
// Combine specular and direct lighting terms. | |
// note: if we make combinedColor "out" only, it throws a potentially uninitialized value warning, so we've made it inout | |
void applyLighting(inout vec4 combinedColor, vec4 albedo, float occlusionFactor) | |
{ | |
// large normal means glowing object | |
if(glow == 1 || (worldNormal.x + worldNormal.y + worldNormal.z) > 2.0f) | |
{ | |
combinedColor = superGlow ? vec4(albedo.xyz * 1.5f, albedo.a) : albedo; | |
return; | |
} | |
vec4 dirLightSpecular = occlusionFactor * specular * dirLightColor; | |
dirLightSpecular *= dirLightSpecularMultiplier; // arbitrary adjustment | |
vec4 dirLightDirect = ((NdotL * dirLightColor) * occlusionFactor) + (dirLightAmbient * occlusionFactor) + (dirShadowColor * (1.0f - occlusionFactor)); | |
if(NdotL <= 0.04f) | |
{ | |
dirLightDirect = dirShadowColor; | |
dirLightSpecular = vec4(0.0f, 0.0f, 0.0f, 0.0f); | |
} | |
else if(NdotL <= 0.1) | |
{ | |
float val = (NdotL - 0.04f) / (0.1f - 0.04f); | |
dirLightDirect = (dirLightDirect * val) + (dirShadowColor * (1.0f - val)); | |
dirLightSpecular = dirLightSpecular * val; | |
} | |
dirLightDirect += accumulatePointLights(); | |
dirLightSpecular.a = length(dirLightSpecular.rgb); | |
dirLightDirect.a *= min(occlusionFactor + 0.75f, 1.0f); | |
combinedColor.rgb = dirLightDirect.rgb * albedo.rgb; | |
combinedColor.a = albedo.a; | |
combinedColor += dirLightSpecular; | |
} | |
// Below two functions adapted from https://www.gamedev.net/articles/programming/graphics/contact-hardening-soft-shadows-made-fast-r4906/ | |
vec2 VogelDiskOffset(int sampleIndex, int samplesCount, float phi) | |
{ | |
float GoldenAngle = 2.39996322972865332f; | |
float r = sqrt(sampleIndex + 0.5f) / sqrt(samplesCount); | |
float theta = sampleIndex * GoldenAngle + phi; | |
float sine, cosine; | |
sine = sin(theta); | |
cosine = cos(theta); | |
return r * vec2(cosine, sine); | |
} | |
float InterleavedGradientNoise(vec2 position_screen) | |
{ | |
vec3 magic = vec3(0.06711056f, 0.00583715f, 52.9829189f); | |
return fract(magic.z * fract(dot(position_screen, magic.xy))); | |
} | |
float csmAdjustment(float index) | |
{ | |
if (shadowSplitCount == 4) | |
{ | |
if (index == 1) | |
return 0.333f; | |
else if (index == 2) | |
return 0.1f; | |
else if (index == 3) | |
return 0.033f; | |
} | |
else if (shadowSplitCount == 3) | |
{ | |
if (index == 1) | |
return 0.333f; | |
else if (index == 2) | |
return 0.075f; | |
} | |
else if (shadowSplitCount == 2) | |
{ | |
if (index == 1) | |
return 0.1f; | |
} | |
return 1.0f; | |
} | |
float getSearchDistance(float dReciever, int index) | |
{ | |
if (searchDistanceNearPlane) | |
return lightSize / dReciever * (dReciever - nearPlane) * (blockerSearchAdjustment ? (bool(index) ? csmAdjustment(index) : 1.0f) : 1.0f); | |
else | |
return blockerSearchDistance * (blockerSearchAdjustment ? (bool(index) ? csmAdjustment(index) : 1.0f) : 1.0f); | |
} | |
vec2 blockerSearch(vec4 shadow_coord, bool ultra) | |
{ | |
float dBlocker; | |
float dReciever = shadow_coord.w; | |
float searchDistance = getSearchDistance(dReciever, int(shadow_coord.z)) * (ultra ? ultraRatio : 1.0f); | |
vec2 offset; | |
float depth; | |
int hit = 0; | |
if (blockerSearchMethod == 0) | |
{ | |
for (int x = -blockerSearchSquareNum; x <= blockerSearchSquareNum; x++) | |
{ | |
for (int y = -blockerSearchSquareNum; y <= blockerSearchSquareNum; y++) | |
{ | |
offset = vec2(x, y) / blockerSearchSquareNum * searchDistance; | |
dBlocker = texture2DArray(stex, vec3(shadow_coord.xy + offset, shadow_coord.z)).x; | |
if (dBlocker < dReciever) | |
{ | |
depth += dBlocker; | |
hit++; | |
} | |
} | |
} | |
} | |
else if (blockerSearchMethod == 1) | |
{ | |
for (int i = 0; i < poissonDiskCount; i++) | |
{ | |
offset = poissonDisk[i] * searchDistance; | |
dBlocker = texture2DArray(stex, vec3(shadow_coord.xy + offset, shadow_coord.z)).x; | |
if (dBlocker < dReciever) | |
{ | |
depth += dBlocker; | |
hit++; | |
} | |
} | |
} | |
else if (blockerSearchMethod == 2) | |
{ | |
for (int i = 0; i < VogelDiskSearchSampleCount; i++) | |
{ | |
offset = VogelDiskOffset(i, VogelDiskSearchSampleCount, (InterleavedGradientNoiseSearchEnabled ? InterleavedGradientNoise(fract(worldPos.xy * worldPos.yz) * InterleavedGradientNoiseFactor) * 6.28318530718f : 0.0f)) * searchDistance; | |
dBlocker = texture2DArray(stex, vec3(shadow_coord.xy + offset, shadow_coord.z)).x; | |
if (dBlocker < dReciever) | |
{ | |
depth += dBlocker; | |
hit++; | |
} | |
} | |
} | |
return vec2(depth / hit, hit); | |
} | |
float calculatePenumbraSize(int index, float dReciever, float depth, bool ultra) | |
{ | |
float penumbraSize; | |
penumbraSize = (dReciever - depth) * lightSize / depth; | |
penumbraSize *= ultra ? ultraRatio : 1.0f; | |
if (chssMinRadius) | |
{ | |
penumbraSize += chssMinPenumbraRadius; | |
} | |
if (chssMaxRadius) | |
{ | |
penumbraSize = min(penumbraSize, searchDistanceNearPlane ? (lightSize / dReciever * (dReciever - nearPlane)) : blockerSearchDistance); | |
} | |
return penumbraSize; | |
} | |
float basicShadow(vec4 shadow_coord) | |
{ | |
return (texture2DArray(stex, vec3(shadow_coord.xyz)).x > shadow_coord.w) ? 1.0f : 0.0f; | |
} | |
float pcf(vec4 shadow_coord, float penumbraSize) | |
{ | |
vec2 offset; | |
float dist; | |
int index; | |
float dist2 = shadow_coord.w; | |
int hit = 0; | |
if (csmAdjustmentEnabled) | |
{ | |
index = int(shadow_coord.z); | |
penumbraSize *= bool(index) ? csmAdjustment(index) : 1.0f; | |
} | |
if (pcfMethod == 0) | |
{ | |
for (int x = -squareFilteringNum; x <= squareFilteringNum; x++) | |
{ | |
for (int y = -squareFilteringNum; y <= squareFilteringNum; y++) | |
{ | |
offset = vec2(x, y) / squareFilteringNum * penumbraSize; | |
dist = texture2DArray(stex, vec3(shadow_coord.xy + offset, shadow_coord.z)).x; | |
if (dist > dist2) | |
{ | |
hit++; | |
} | |
} | |
} | |
return float (hit) / pow(squareFilteringNum * 2 + 1, 2); | |
} | |
else if (pcfMethod == 1) | |
{ | |
for (int i = 0; i < poissonDiskCount; i++) | |
{ | |
offset = poissonDisk[i] * penumbraSize; | |
dist = texture2DArray(stex, vec3(shadow_coord.xy + offset, shadow_coord.z)).x; | |
if (dist > dist2) | |
{ | |
hit++; | |
} | |
} | |
return float(hit) / poissonDiskCount; | |
} | |
else if (pcfMethod == 2) | |
{ | |
int hit1 = 0; | |
int hit2 = 0; | |
for (int x = -squareFilteringNum; x <= squareFilteringNum; x++) | |
{ | |
for (int y = -squareFilteringNum; y <= squareFilteringNum; y++) | |
{ | |
offset = vec2(x, y) / squareFilteringNum * penumbraSize; | |
dist = texture2DArray(stex, vec3(shadow_coord.xy + offset, shadow_coord.z)).x; | |
if (dist > dist2) | |
{ | |
hit1++; | |
} | |
} | |
} | |
for (int i = 0; i < poissonDiskCount; i++) | |
{ | |
offset = poissonDisk[i] * penumbraSize; | |
dist = texture2DArray(stex, vec3(shadow_coord.xy + offset, shadow_coord.z)).x; | |
if (dist > dist2) | |
{ | |
hit2++; | |
} | |
} | |
return (float(hit1) / pow(squareFilteringNum * 2 + 1, 2)) * pcfBlend + (float(hit2) / poissonDiskCount) * (1.0f - pcfBlend); | |
} | |
else if (pcfMethod == 3) | |
{ | |
for (int i = 0; i < VogelDiskFilterSampleCount; i++) | |
{ | |
offset = VogelDiskOffset(i, VogelDiskFilterSampleCount, (InterleavedGradientNoiseFilteringEnabled ? InterleavedGradientNoise(fract(worldPos.xy * worldPos.yz) * InterleavedGradientNoiseFactor) * 6.28318530718f : 0.0f)) * penumbraSize; | |
dist = texture2DArray(stex, vec3(shadow_coord.xy + offset, shadow_coord.z)).x; | |
if (dist > dist2) | |
{ | |
hit++; | |
} | |
} | |
return float(hit) / VogelDiskFilterSampleCount; | |
} | |
} | |
float shadowSampleCHSS(vec4 shadow_coord, bool ultra) | |
{ | |
// Step 1: Blocker Search | |
vec2 blockerSearch = blockerSearch(shadow_coord, ultra); | |
if (blockerSearch.y < 1) | |
{ | |
return basicShadow(shadow_coord); | |
} | |
// Step 2: Penumbra Size Calculation | |
float penumbraSize = calculatePenumbraSize(int(shadow_coord.z), shadow_coord.w, blockerSearch.x, ultra); | |
// Step 3: Percentage-Closer Filtering | |
return pcf(shadow_coord, penumbraSize); | |
} | |
float advancedShadowCoef() | |
{ | |
vec4 shadow_coordA = vec4(0.0f, 0.0f, 0.0f, 0.0f); | |
vec4 shadow_coordB = vec4(0.0f, 0.0f, 0.0f, 0.0f); | |
float blend = 0.0f; | |
calculateShadowCoords(shadow_coordA, shadow_coordB, blend); | |
float sampleA; | |
if (CHSS == true) | |
{ | |
if (ultra == true) | |
sampleA = shadowSampleCHSS(shadow_coordA, false) * ultraWeightFactor + shadowSampleCHSS(shadow_coordA, true) * (1.0f - ultraWeightFactor); | |
else if (!defaultShadows) | |
sampleA = shadowSampleCHSS(shadow_coordA, false); | |
else | |
sampleA = basicShadow(shadow_coordA); | |
} | |
if (CHSS == false) | |
{ | |
if (ultra == true) | |
sampleA = pcf(shadow_coordA, sampleDistance) * ultraWeightFactor + pcf(shadow_coordA, sampleDistance * ultraRatio) * (1.0f - ultraWeightFactor); | |
else if (!defaultShadows) | |
sampleA = pcf(shadow_coordA, sampleDistance); | |
else | |
sampleA = basicShadow(shadow_coordA); | |
} | |
if (blend > 0.0f) | |
{ | |
float sampleB; | |
if (CHSS == true) | |
{ | |
if (ultra) | |
sampleB = shadowSampleCHSS(shadow_coordB, false) * ultraWeightFactor + shadowSampleCHSS(shadow_coordB, true) * (1 - ultraWeightFactor); | |
else if (!defaultShadows) | |
sampleB = shadowSampleCHSS(shadow_coordB, false); | |
else | |
sampleB = basicShadow(shadow_coordB); | |
} | |
if (CHSS == false) | |
{ | |
if (ultra == true) | |
sampleB = pcf(shadow_coordB, sampleDistance) * ultraWeightFactor + pcf(shadow_coordB, sampleDistance * ultraRatio) * (1.0f - ultraWeightFactor); | |
else if (!defaultShadows) | |
sampleB = pcf(shadow_coordB, sampleDistance); | |
else | |
sampleB = basicShadow(shadow_coordB); | |
} | |
return clamp((sampleB * blend) + (sampleA * (1.0f - blend)), 0.0f, 1.0f); | |
} | |
else | |
{ | |
return sampleA; | |
} | |
} | |
// Taken and modified from Hata's Shader Toggle | |
void basicCalculateShadowCoords(inout vec4 shadow_coordA, float fudgeKeyB) | |
{ | |
int index = 3; | |
float fudgeFactorB = fudgeKeyB / zScale.w; | |
if(vPos.y < far_d.x) | |
{ | |
index = 0; | |
fudgeFactorB = fudgeKeyB / zScale.x; | |
} | |
else if(vPos.y < far_d.y) | |
{ | |
index = 1; | |
fudgeFactorB = fudgeKeyB / zScale.y; | |
} | |
else if(vPos.y < far_d.z) | |
{ | |
index = 2; | |
fudgeFactorB = fudgeKeyB / zScale.z; | |
} | |
shadow_coordA = gl_TextureMatrix[index]*vPos; | |
shadow_coordA.w = shadow_coordA.z - fudgeFactorB; // Figure the input coordinate for PCF sampling if appropriate. | |
shadow_coordA.z = float(index); // Encode the layer to sample. | |
} | |
float basicShadowCoef(float fudgeKeyB) | |
{ | |
vec4 shadow_coordA; | |
basicCalculateShadowCoords(shadow_coordA, fudgeKeyB); | |
float shadowA = texture2DArray(stex, shadow_coordA.xyz).x; // get the stored depth | |
float diffA = shadowA - shadow_coordA.w; // get the difference of the stored depth and the distance of this fragment to the light | |
if(diffA > 0.0f) | |
diffA = 1.0f; | |
return diffA; | |
} | |
float shadowCoef(bool isLight) | |
{ | |
float coef = 0.0f; | |
if (particleOptimization) | |
{ | |
if(!isLight) | |
coef = advancedShadowCoef(); | |
else | |
coef = basicShadowCoef(0.1f); | |
} | |
else | |
coef = advancedShadowCoef(); | |
return coef; | |
} | |
// End Hata's Shader Toggle rip | |
void main() | |
{ | |
vec4 albedo = vec4(0.0f, 0.0f, 0.0f, 0.0f); | |
calculateSurface(gl_Color, albedo); | |
float occlusionFactor = 0.0f; | |
if(NdotL > -0.01f) | |
{ | |
if(shadowSplitCount <= 0) | |
{ | |
occlusionFactor = 1.0f; | |
} | |
else if(isParticle == 1) | |
{ | |
occlusionFactor = shadowCoef(true); | |
} | |
else | |
{ | |
occlusionFactor = shadowCoef(false); | |
} | |
} | |
// Apply lighting and fog. | |
vec4 fragColor = vec4(0.0f, 0.0f, 0.0f, 0.0f); | |
if (isParticle == 1) | |
{ | |
vec4 texAlbedo = texture2D(tex, texCoord); | |
vec4 dirLightDirect = (dirLightColor * occlusionFactor) + (dirLightAmbient * occlusionFactor) + (dirShadowColor * (1.0f - occlusionFactor)); | |
vec4 plt = accumulateParticlePointLights(); | |
vec4 lightTotal = dirLightDirect + plt; | |
lightTotal.x = clamp(lightTotal.x, 0.0f, 1.2f); | |
lightTotal.y = clamp(lightTotal.y, 0.0f, 1.2f); | |
lightTotal.z = clamp(lightTotal.z, 0.0f, 1.2f); | |
fragColor = texAlbedo * gl_Color * lightTotal; | |
applyFog(fragColor, occlusionFactor); | |
fragColor.a = texAlbedo.a * gl_Color.a; | |
} | |
else | |
{ | |
if (shadowOpacity) | |
{ | |
applyLighting(fragColor, albedo, 1 - (1 - occlusionFactor) * occlusionBlend); | |
} | |
else | |
{ | |
applyLighting(fragColor, albedo, occlusionFactor); | |
} | |
applyFog(fragColor, occlusionFactor); | |
} | |
// Uncomment to viz depth in B. | |
//fragColor.z = vPos.y * 0.01f; | |
if (debugDisplayMode == 0) | |
{ | |
gl_FragColor = fragColor; | |
} | |
else if (debugDisplayMode == 1) | |
{ | |
gl_FragColor = vec4(occlusionFactor, occlusionFactor, occlusionFactor, fragColor.a); | |
} | |
else if (debugDisplayMode == 2) | |
{ | |
gl_FragColor = vec4(fract(worldPos), fragColor.a); | |
} | |
else if (debugDisplayMode == 3) | |
{ | |
gl_FragColor = vec4(worldNormal, fragColor.a); | |
} | |
else if (debugDisplayMode == 4) | |
{ | |
gl_FragColor = albedo; | |
} | |
else if (debugDisplayMode == 5) | |
{ | |
gl_FragColor = vec4(reflectVec, fragColor.a); | |
} | |
else if (debugDisplayMode == 6) | |
{ | |
gl_FragColor = viewDelta; | |
} | |
else if (debugDisplayMode == 7) | |
{ | |
gl_FragColor = fract(vPos); | |
} | |
else if (debugDisplayMode == 8) | |
{ | |
gl_FragColor = vec4(texCoord, 0.0f, fragColor.a); | |
} | |
} | |
/* Relevant Files | |
CSM | |
http://developer.download.nvidia.com/SDK/10.5/opengl/src/cascaded_shadow_maps/doc/cascaded_shadow_maps.pdf | |
CHSS/PCSS | |
https://web.archive.org/web/20050903002824/http://www.randima.com:80/MastersThesis.pdf | |
https://http.download.nvidia.com/developer/presentations/2005/SIGGRAPH/Percentage_Closer_Soft_Shadows.pdf | |
http://developer.download.nvidia.com/presentations/2008/GDC/GDC08_SoftShadowMapping.pdf | |
http://developer.download.nvidia.com/shaderlibrary/docs/shadow_PCSS.pdf | |
https://www.realtimeshadows.com/sites/default/files/sig2013-course-softshadows.pdf | |
https://maxest.gct-game.net/content/chss.pdf | |
*/ |
Soft shadow size is now roughly consistent across shadow cascades when using not using PCSS.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Fixed fog when using the shadowOpacity option