Skip to content

Instantly share code, notes, and snippets.

@QuadStorm
Created June 3, 2018 02:07
Show Gist options
  • Save QuadStorm/ac9b5ddff1493feea8f2984af89856f0 to your computer and use it in GitHub Desktop.
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.
#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