Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #version 120
- #extension GL_EXT_texture_array : require
- #extension GL_EXT_texture_array : enable
- // Port's Poisson Disc (Optimized) Soft Shadow Shader (2015)*
- // - Now with an ultra graphics version, with proper blending this time...*
- // And various additions*
- // Configuration: For the adventurous!
- // Show only shadows?
- bool debug = false;
- // Ultra Mode; use 2 shadows layered for fancier graphics
- bool ultraMode = true;
- // Point Light Brightness (lightFactor), Exposure Control (exposureFactor) (only used in ultra mode)
- float lightFactor = 0.25f;
- float exposureFactor = 1.0f;
- // http://forum.blockland.us/index.php?topic=289446.0
- float occlusionBlend = 0.875f; //1.0f
- bool interiorLightingFix = true; // toggles above fix; above value ignored (set to 1.0f) regardless of setting if false
- // Specular Lighting
- float dirLightSpecularFactor = 0.5f; //0.5f
- // 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.5f; // 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.1f; //0.1f //0.3f ultra
- //const float fudgeFactor2 = 0.15f; //0.25f
- //const float fudgeFactor3 = 1.0f; //0.7f
- //const float fudgeFactor4 = 1.5f; //2.66f
- const float fudgeFactor1 = 0.2f; //0.1f
- const float fudgeFactor2 = 0.5f; //0.25f
- const float fudgeFactor3 = 1.2f; //0.7f
- const float fudgeFactor4 = 2.8f; //2.66f
- // 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
- // normal is always used, ambient is used in ultra mode
- float normalSampleDistance = 1.0f / 800.0f;
- float ambientSampleDistance = 1.0f / 200.0f;
- // Magic numbers below
- int poissonDiskCount = 32;
- vec2 poissonDisk[59] = 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),
- //below...
- vec2(-0.05151585f, 0.3436534f),
- vec2(0.3648908f, 0.2827295f),
- vec2(-0.2478754f, 0.186921f),
- vec2(0.1171809f, 0.1482293f),
- vec2(-0.1496224f, 0.6990415f),
- vec2(-0.456594f, 0.378567f),
- vec2(-0.4242465f, -0.001935145f),
- vec2(-0.1889321f, -0.2015685f),
- vec2(0.1480272f, 0.6432338f),
- vec2(-0.5046303f, 0.8245607f),
- vec2(0.001617888f, 0.9789896f),
- vec2(-0.6228038f, 0.5963655f),
- vec2(0.4185582f, 0.7959766f),
- vec2(0.06965782f, -0.1184023f),
- vec2(-0.8310863f, 0.2197417f),
- vec2(-0.869589f, 0.4893173f),
- vec2(-0.6366982f, -0.357598f),
- vec2(-0.2509329f, -0.5531961f),
- vec2(-0.03994134f, -0.4170877f),
- vec2(-0.675245f, -0.0009701257f),
- vec2(0.3373009f, -0.4531572f),
- vec2(0.3022793f, -0.02336982f),
- vec2(0.6078352f, 0.5235748f),
- vec2(-0.9277961f, -0.05385896f),
- vec2(0.3847639f, -0.7718652f),
- vec2(0.5278201f, -0.168486f),
- vec2(0.1269102f, -0.8461399f),
- vec2(0.7260014f, -0.4588331f),
- vec2(-0.8775687f, -0.450681f),
- vec2(-0.574103f, -0.7766181f),
- vec2(0.6930821f, 0.2592674f),
- vec2(-0.3360346f, -0.8594083f),
- vec2(-0.2591985f, 0.9300818f),
- vec2(0.939391f, -0.2374034f),
- vec2(0.8332635f, 0.01952092f)
- );
- // This has way too much acne
- // int poissonDiskCount = 35;
- // vec2 poissonDisk[35] = vec2[](
- // vec2(-0.05151585f, 0.3436534f),
- // vec2(0.3648908f, 0.2827295f),
- // vec2(-0.2478754f, 0.186921f),
- // vec2(0.1171809f, 0.1482293f),
- // vec2(-0.1496224f, 0.6990415f),
- // vec2(-0.456594f, 0.378567f),
- // vec2(-0.4242465f, -0.001935145f),
- // vec2(-0.1889321f, -0.2015685f),
- // vec2(0.1480272f, 0.6432338f),
- // vec2(-0.5046303f, 0.8245607f),
- // vec2(0.001617888f, 0.9789896f),
- // vec2(-0.6228038f, 0.5963655f),
- // vec2(0.4185582f, 0.7959766f),
- // vec2(0.06965782f, -0.1184023f),
- // vec2(-0.8310863f, 0.2197417f),
- // vec2(-0.869589f, 0.4893173f),
- // vec2(-0.6366982f, -0.357598f),
- // vec2(-0.2509329f, -0.5531961f),
- // vec2(-0.03994134f, -0.4170877f),
- // vec2(-0.675245f, -0.0009701257f),
- // vec2(0.3373009f, -0.4531572f),
- // vec2(0.3022793f, -0.02336982f),
- // vec2(0.6078352f, 0.5235748f),
- // vec2(-0.9277961f, -0.05385896f),
- // vec2(0.3847639f, -0.7718652f),
- // vec2(0.5278201f, -0.168486f),
- // vec2(0.1269102f, -0.8461399f),
- // vec2(0.7260014f, -0.4588331f),
- // vec2(-0.8775687f, -0.450681f),
- // vec2(-0.574103f, -0.7766181f),
- // vec2(0.6930821f, 0.2592674f),
- // vec2(-0.3360346f, -0.8594083f),
- // vec2(-0.2591985f, 0.9300818f),
- // vec2(0.939391f, -0.2374034f),
- // vec2(0.8332635f, 0.01952092f)
- // );
- // 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 line 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)
- {
- // Calculate fog.
- vec4 fogColor = texture2D(fogTex, fogCoords) * fogBaseColor;
- // Blend it.
- 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 = albedo;
- return;
- }
- vec4 dirLightSpecular = occlusionFactor * specular * dirLightColor;
- dirLightSpecular *= dirLightSpecularFactor; //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() * lightFactor;
- 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 poissonSample(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 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;
- sampleA = ultraMode ? (poissonSample(shadow_coordA, normalSampleDistance) + poissonSample(shadow_coordA, ambientSampleDistance)) / 2 : poissonSample(shadow_coordA, normalSampleDistance);
- if (blend > 0.0f)
- {
- float sampleB;
- sampleB = ultraMode ? (poissonSample(shadow_coordB, normalSampleDistance) + poissonSample(shadow_coordB, ambientSampleDistance)) / 2 : poissonSample(shadow_coordB, normalSampleDistance);
- return clamp((sampleB * blend) + (sampleA * (1.0f - blend)), 0.0f, 1.0f) * exposureFactor;
- }
- return sampleA * exposureFactor;
- }
- 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);
- fragColor.a = texAlbedo.a * gl_Color.a;
- }
- else
- {
- if (interiorLightingFix)
- applyLighting(fragColor, albedo, 1 - (1 - occlusionFactor) * occlusionBlend);
- else
- applyLighting(fragColor, albedo, occlusionFactor);
- applyFog(fragColor);
- }
- // 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);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement