Created
June 3, 2018 02:07
-
-
Save QuadStorm/ac9b5ddff1493feea8f2984af89856f0 to your computer and use it in GitHub Desktop.
A highly configurable shader file for Blockland with several fancy features including PCSS.
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 | |
#extension GL_EXT_gpu_shader4 : require | |
#extension GL_EXT_gpu_shader4 : enable | |
// Port's Poisson Disc (Optimized) Soft Shadow Shader (2015), modified by Stealth Commander/QuadStorm | |
// Includes an ultra graphics version, a Percentage-Closer Soft Shadows (PCSS) implementation, and other smaller configuration variables | |
// Revision '5' Release | |
// Configuration: For the adventurous! | |
// Configuration Guide | |
// |default - the values as released as a reference for tuning| | |
// debug - show only shadows? |false| | |
// ultraMode - use 2 shadow sample layers ontop of eachother for an 'ultra' graphics effect |false| | |
// ultraRatio - ratio in size between the normal and ambient samples |5.0f| | |
// PCSSToggle - toggles PCSS (dynamic soft shadow variance by distance) |true| | |
// depthLoopNumber - sampling loop amount around each distance point: 1 = 3x3, 2 = 5x5, 3 = 7x7, etc. |2| | |
// lightSize - how large the light source is -- the larger the softer shadows get faster. larger values can get messy |0.2f| | |
// searchDistance - the shadow depth search distance -- higher values don't 'bleed' enough and lower values are less precise with shadow depths; /decrease/ for smaller lightsizes, /increase/ for larger ones |1.0f / 1536.0f| | |
// superGlow - Off-like glow effect; works correctly for transparent glowing bricks |true| | |
// shadowOpacity - allows for changing how transparent/opaque shadows are -- see https://forum.blockland.us/index.php?topic=289446.0; this toggles the fix |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) |0.925f| | |
// 'Perfection' can be very hard to come by. You'll probably have to tweak settings per situation to get things right. | |
// Ultra Mode; tends to look better with PCSS off, but you can have both on if you must | |
bool ultraMode = false; | |
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; | |
// PCSS, aka fighting everything that's wrong with shadow maps | |
// but could look good if you get the variables balanced right | |
// fixed sampleDistance far below used when false | |
bool PCSSToggle = true; | |
int depthLoopNumber = 3; | |
float lightSize = 0.25f; // 0.05 - 0.5 depending on context | |
float searchDistance = 1.0f / 100.0f; | |
bool poissonDepth = false; // poisson depth sampling | |
// PCSS radii clamping; this aims to mitigate the horrible looking effects of large radii and force a minimum of shadow softness | |
bool pcssClampRadii = false; | |
float pcssMinRadius = 0.0001f; // 5000 | 0.0002 | |
float pcssMaxRadius = 0.02f; // 250 | 0.004 | |
// Basic Box PCF (no poisson, a la other soft shadow methods) | |
bool pcfSampler = true; | |
int pcfNum = 6; | |
// a try at less sampling when not needed - quality/performance optimization | |
bool pcfOptimization = true; | |
// Fog | |
bool linearFog = false; // faster, but sorta less realistic | |
float fogExp = 1.0f; | |
// Superglow | |
bool superGlow = true; | |
// Shadow Opacity | |
bool shadowOpacity = true; | |
float occlusionBlend = 0.925f; | |
// 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. | |
// Blending only works with ultra mode off, since I (not port) can not figure this out | |
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; | |
const float fudgeFactor2 = 0.5f; | |
const float fudgeFactor3 = 1.5f; | |
const float fudgeFactor4 = 5.0f; | |
// 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're a good starting point | |
float sampleDistance = 1.0f / 100.0f; | |
// Magic numbers below | |
int poissonDiskCount = 135; | |
vec2 poissonDisk[135] = vec2[] | |
( | |
vec2(0, 0), | |
vec2(0.0951336, -0.1457852), | |
vec2(-0.1244571, -0.1191383), | |
vec2(-0.06589106, 0.1528488), | |
vec2(-0.1134799, -0.01447811), | |
vec2(-0.1374047, -0.2194312), | |
vec2(0.00450462, -0.2047105), | |
vec2(0.1119988, 0.05098353), | |
vec2(0.2288575, -0.06912366), | |
vec2(-0.2133227, 0.02454831), | |
vec2(0.1111896, 0.1807129), | |
vec2(0.2559151, 0.02961993), | |
vec2(0.3407415, -0.07578353), | |
vec2(0.2563416, -0.2436545), | |
vec2(-0.1701523, 0.1683661), | |
vec2(0.1965078, -0.4170507), | |
vec2(0.1183021, -0.2830924), | |
vec2(-0.01656891, -0.3364981), | |
vec2(-0.254407, -0.2527578), | |
vec2(-0.4078597, -0.228698), | |
vec2(-0.3459725, -0.3678785), | |
vec2(0.2611208, -0.5687482), | |
vec2(0.05222826, -0.4770998), | |
vec2(0.1594227, -0.7015165), | |
vec2(0.2840366, -0.6748313), | |
vec2(-0.3264929, -0.1505083), | |
vec2(-0.5535817, -0.2131963), | |
vec2(-0.00959465, -0.8068637), | |
vec2(0.064941, -0.643945), | |
vec2(0.2717584, -0.8386889), | |
vec2(-0.1910821, -0.4466026), | |
vec2(-0.5111607, -0.423937), | |
vec2(0.379738, -0.8019445), | |
vec2(-0.3860002, -0.5012952), | |
vec2(-0.6750128, -0.5125482), | |
vec2(0.4067858, -0.9025675), | |
vec2(0.4950482, -0.6575115), | |
vec2(-0.5073444, -0.6144094), | |
vec2(-0.08645296, 0.2604458), | |
vec2(-0.6786309, -0.3579207), | |
vec2(-0.8759595, -0.3427323), | |
vec2(0.5233065, -0.4795123), | |
vec2(0.5770249, -0.5666536), | |
vec2(0.3506554, -0.5032448), | |
vec2(0.05563826, -0.9132139), | |
vec2(0.08806939, -0.7815942), | |
vec2(0.7659222, -0.5198661), | |
vec2(-0.2904063, 0.2057745), | |
vec2(0.495086, -0.7972633), | |
vec2(-0.7750046, -0.2942277), | |
vec2(-0.1838527, -0.8644153), | |
vec2(-0.06777722, -0.9496753), | |
vec2(0.3823927, 0.1203214), | |
vec2(0.4139371, 0.2589353), | |
vec2(-0.3244419, 0.01984585), | |
vec2(-0.3697801, 0.1100583), | |
vec2(-0.8288329, -0.4809016), | |
vec2(0.3429501, -0.3237988), | |
vec2(-0.5749199, -0.3365948), | |
vec2(0.6363789, -0.4035244), | |
vec2(-0.1754244, -0.7338435), | |
vec2(-0.2328039, 0.3389311), | |
vec2(-0.3044877, -0.5779614), | |
vec2(-0.4703759, 0.1353574), | |
vec2(0.3635537, -0.6099477), | |
vec2(0.7902213, -0.3691019), | |
vec2(0.604952, -0.7716019), | |
vec2(-0.6491721, 0.2100721), | |
vec2(0.407153, 0.4124183), | |
vec2(0.2635823, 0.1884831), | |
vec2(-0.5571768, 0.06792152), | |
vec2(0.4192934, -0.1522004), | |
vec2(0.8890129, -0.3393337), | |
vec2(0.4015584, 0.01058372), | |
vec2(0.2435132, 0.3321772), | |
vec2(0.5214001, -0.2958628), | |
vec2(0.5332999, 0.3964668), | |
vec2(0.2882766, 0.5295519), | |
vec2(0.8763232, -0.2319224), | |
vec2(0.7375241, -0.2650713), | |
vec2(0.8960116, -0.442726), | |
vec2(0.5325155, 0.08337001), | |
vec2(0.5671927, -0.06184172), | |
vec2(0.4954312, 0.5668753), | |
vec2(-0.02598101, 0.3976752), | |
vec2(0.08789875, 0.3352225), | |
vec2(-0.1313136, 0.4161511), | |
vec2(0.6276786, 0.6873559), | |
vec2(0.5912785, -0.1845674), | |
vec2(0.4185997, -0.2523295), | |
vec2(-0.5374222, -0.03362173), | |
vec2(-0.6922106, -0.1171541), | |
vec2(-0.1403162, 0.5610359), | |
vec2(-0.5648803, 0.3398148), | |
vec2(-0.4521095, 0.4548817), | |
vec2(0.7312721, 0.02824391), | |
vec2(-0.4362847, 0.2814974), | |
vec2(-0.5887011, 0.5207564), | |
vec2(-0.3412226, -0.7056051), | |
vec2(-0.6363071, 0.00310753), | |
vec2(-0.02171745, 0.6717157), | |
vec2(0.1501283, 0.6256612), | |
vec2(-0.7416134, 0.4596929), | |
vec2(-0.5666857, 0.6250131), | |
vec2(-0.8129191, -0.1920015), | |
vec2(-0.8548332, -0.08355456), | |
vec2(-0.4705517, 0.5749201), | |
vec2(-0.8407493, 0.3725242), | |
vec2(-0.1420833, 0.7480395), | |
vec2(-0.2413939, 0.6520627), | |
vec2(0.01996444, 0.4971052), | |
vec2(-0.313913, 0.5066901), | |
vec2(-0.8788791, 0.03306975), | |
vec2(-0.6664616, 0.7332086), | |
vec2(-0.3788642, 0.6391957), | |
vec2(0.127771, 0.4344893), | |
vec2(-0.6868327, 0.6078894), | |
vec2(-0.4726286, 0.6907672), | |
vec2(0.5142618, 0.7352716), | |
vec2(-0.4096418, 0.79397), | |
vec2(-0.9652838, -0.1078783), | |
vec2(0.05344208, 0.8427666), | |
vec2(0.7249011, 0.5268908), | |
vec2(0.7722252, 0.625686), | |
vec2(0.12518, 0.7605301), | |
vec2(-0.9623628, 0.1637841), | |
vec2(-0.7457262, 0.1424999), | |
vec2(-0.8787336, 0.2578501), | |
vec2(0.08879758, 0.9647315), | |
vec2(-0.06732855, 0.9499662), | |
vec2(0.1972721, 0.8491885), | |
vec2(0.2701098, 0.7291467), | |
vec2(0.3723929, 0.8447194), | |
vec2(0.4032576, 0.7399523), | |
vec2(0.2845929, 0.9401256) | |
); | |
bool debug = false; | |
// 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), 12.0f) * 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 (!linearFog) | |
albedo = mix(albedo, fogColor, pow((0.5f + 1.0f / 2.0f * sin(fogColor.a * 3.141592654f - 1.570796327f)), fogExp)); | |
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; | |
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; | |
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 *= 0.5f; // 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; | |
} | |
float poissonSampleO(vec4 shadow_coord, float spread) | |
{ | |
int hit = 0; | |
for (int i = 0; i < poissonDiskCount; i++) { | |
float dist = texture2DArray(stex, vec3(shadow_coord.xy + poissonDisk[i] * spread, shadow_coord.z)).x; | |
if (dist - shadow_coord.w > 0.0f) | |
hit++; | |
} | |
return float(hit) / poissonDiskCount; | |
} | |
float pcfSample(vec4 shadow_coord, float spread) | |
{ | |
int hit = 0; | |
int pcfLoops = 0; | |
if (pcfOptimization) | |
{ | |
bool test = abs(spread) <= 0.0005f; | |
if (test) | |
{ | |
float pcfTest = pcfNum / 2; | |
pcfTest = floor(pcfTest); | |
pcfNum = int(pcfTest); | |
} | |
} | |
for (int x = -pcfNum; x <= pcfNum; x++) | |
{ | |
for (int y = -pcfNum; y <= pcfNum; y++) | |
{ | |
float dist = texture2DArray(stex, vec3(shadow_coord.xy + vec2(x, y) / (pcfNum == 0 ? 1 : pcfNum) * spread, shadow_coord.z)).x; | |
if (dist - shadow_coord.w > 0.0f) | |
{ | |
hit++; | |
} | |
pcfLoops++; | |
} | |
} | |
return float (hit) / pcfLoops; | |
} | |
float poissonSample(vec4 shadow_coord, float spread) | |
{ | |
if (!pcfSampler) | |
return poissonSampleO(shadow_coord, spread); | |
else | |
return pcfSample(shadow_coord, spread); | |
} | |
float distanceCalcExper(vec4 shadow_coord, float searchDistance, float lightSize) | |
{ | |
float pcfDepth; | |
for (int i = 0; i < poissonDiskCount; i++) | |
{ | |
// depth check here? | |
pcfDepth -= (texture2DArray(stex, vec3(shadow_coord.xy + poissonDisk[i] * searchDistance, shadow_coord.z)).x - shadow_coord.w) * lightSize / texture2DArray(stex, vec3(shadow_coord.xy + poissonDisk[i] * searchDistance, shadow_coord.z)).x; | |
} | |
if (pcssClampRadii) | |
return clamp(pcfDepth / poissonDiskCount, pcssMinRadius, pcssMaxRadius); | |
else | |
return pcfDepth / poissonDiskCount; | |
} | |
float distanceCalcOriginal(vec4 shadow_coord, int loopNumber, float searchDistance, float lightSize) | |
{ | |
float pcfDepth; | |
int loop; | |
int loopCount; | |
for (int x = -loopNumber; x <= loopNumber; x++) | |
{ | |
for (int y = -loopNumber; y <= loopNumber; y++) | |
{ | |
pcfDepth -= (texture2DArray(stex, vec3(shadow_coord.xy + vec2(x, y) * searchDistance / (loopNumber * 2 + 1), shadow_coord.z)).x - shadow_coord.w) * lightSize / texture2DArray(stex, vec3(shadow_coord.xy + vec2(x, y) * searchDistance, shadow_coord.z)).x; | |
loopCount++; | |
} | |
} | |
if (pcssClampRadii) | |
return clamp(pcfDepth / loopCount, pcssMinRadius, pcssMaxRadius); | |
else | |
return pcfDepth / loopCount; | |
} | |
float distanceCalc(vec4 shadow_coord, int loopNumber, float searchDistance, float lightSize) | |
{ | |
if (poissonDepth) | |
return distanceCalcExper(shadow_coord, searchDistance, lightSize); | |
else | |
return distanceCalcOriginal(shadow_coord, loopNumber, searchDistance, lightSize); | |
} | |
float shadowCoef() | |
{ | |
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; | |
float sampleADistance; | |
float sampleBDistance; | |
if (PCSSToggle == true) | |
{ | |
sampleADistance = pow(distanceCalc(shadow_coordA, depthLoopNumber, searchDistance, lightSize), 1); | |
if (ultraMode == true) | |
sampleA = (poissonSample(shadow_coordA, sampleADistance) * ultraWeightFactor + poissonSample(shadow_coordA, pow(distanceCalc(shadow_coordA, depthLoopNumber, searchDistance * ultraRatio, lightSize * ultraRatio), 1)) * (1 - ultraWeightFactor)); | |
else | |
sampleA = poissonSample(shadow_coordA, sampleADistance); | |
} | |
if (PCSSToggle == false) | |
{ | |
if (ultraMode == true) | |
sampleA = (poissonSample(shadow_coordA, sampleDistance) * ultraWeightFactor + poissonSample(shadow_coordA, sampleDistance * ultraRatio) * (1.0f - ultraWeightFactor)); | |
else | |
sampleA = poissonSample(shadow_coordA, sampleDistance); | |
} | |
if (blend > 0.0f) | |
{ | |
float sampleB; | |
if (PCSSToggle == true) | |
{ | |
sampleBDistance = pow(distanceCalc(shadow_coordB, depthLoopNumber, searchDistance, lightSize), 1); | |
if (ultraMode) | |
sampleB = (poissonSample(shadow_coordB, sampleBDistance) * ultraWeightFactor + poissonSample(shadow_coordB, pow(distanceCalc(shadow_coordB, depthLoopNumber, searchDistance * ultraRatio, lightSize * ultraRatio), 1)) * (1 - ultraWeightFactor)); | |
else | |
sampleB = poissonSample(shadow_coordB, sampleBDistance); | |
} | |
if (PCSSToggle == false) | |
{ | |
if (ultraMode == true) | |
sampleB = (poissonSample(shadow_coordB, sampleDistance) * ultraWeightFactor + poissonSample(shadow_coordB, sampleDistance * ultraRatio) * (1.0f - ultraWeightFactor)); | |
else | |
sampleB = poissonSample(shadow_coordB, sampleDistance); | |
} | |
return clamp((sampleB * blend) + (sampleA * (1.0f - blend)), 0.0f, 1.0f); | |
} | |
return sampleA; | |
return sampleA * (1.0f - clamp((sampleDistance / 0.005f), 0.0f, 1.0f)); | |
} | |
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 | |
occlusionFactor = shadowCoef(); | |
} | |
// 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; | |
gl_FragColor = fragColor; | |
// Uncomment to show shadows only | |
if (debug) | |
gl_FragColor = vec4(occlusionFactor, occlusionFactor, occlusionFactor, 1); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment