Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Do not change samples unless you change it in SSAO_INIT!
- #define SAMPLES 16
- varying vec2 vTexCoord;
- uniform sampler2D uDepthBuffer;
- uniform sampler2D uNormalBuffer;
- uniform sampler2D uNoiseBuffer;
- uniform float uCamNear;
- uniform float uCamFar;
- uniform mat4 uProjMatrix;
- uniform mat4 uProjMatrixInv;
- uniform vec2 uScreenSize;
- uniform vec3 uSSAOKernel[16];
- uniform float uSSAORadius;
- uniform float uSSAOStrength;
- uniform float uSSAOPower;
- // Get Depth Value
- float unpackDepth(vec4 c){
- return clamp(c.r + c.g / 255.0 + c.b / (255.0 * 255.0), 0.0, 1.0);
- }
- // Get Normal Value
- vec3 unpackNormal(vec4 c) {
- return normalize(c.xyz * 2.0 - 1.0);
- }
- // Transform linear depth to exponential depth
- float transformDepth(float depth) {
- return (uCamFar - (uCamNear * uCamFar) / (depth * (uCamFar - uCamNear) + uCamNear)) / (uCamFar - uCamNear);
- }
- // Reconstruct a position from a screen space coordinate and (linear) depth
- vec3 posFromBuffer(vec2 coord, float depth) {
- vec4 pos = uProjMatrixInv * vec4(coord.x * 2.0 - 1.0, 1.0 - coord.y * 2.0, transformDepth(depth), 1.0);
- return pos.xyz / pos.w;
- }
- void main() {
- // Perform alpha test to ignore background
- if (texture2D(uDepthBuffer,vTexCoord).a < 1.0)
- discard;
- // Get view space origin
- float originDepth = unpackDepth(texture2D(uDepthBuffer,vTexCoord));
- vec3 origin = posFromBuffer(vTexCoord, originDepth);
- // Get scaled radius
- float sampleRadius = uSSAORadius * (1.0 - originDepth);
- // Get normal
- vec3 normal = unpackNormal(texture2D(uNormalBuffer, vTexCoord));
- // Random vector from noise
- vec2 noiseScale = (uScreenSize / 4.0);
- vec3 randVec = unpackNormal(texture2D(uNoiseBuffer, vTexCoord * noiseScale));
- // Construct kernel basis matrix
- vec3 tangent = normalize(randVec - normal * dot(randVec, normal));
- vec3 bitangent = cross(tangent, normal);
- mat3 kernelBasis = mat3(tangent, bitangent, normal);
- // Calculate occlusion factor
- float occlusion = 0.0;
- for (int i = 0; i < SAMPLES; i++) {
- // Get sample position
- vec3 samplePos = origin + kernelBasis * uSSAOKernel[i] * sampleRadius;
- // Project sample position
- vec4 sampleScreen = uProjMatrix * vec4(samplePos, 1.0);
- vec2 sampleTex = (sampleScreen.xy / sampleScreen.w) * 0.5 + 0.5;
- sampleTex.y = 1.0 - sampleTex.y;
- // Get sample depth
- float sampleDepth = posFromBuffer(sampleTex, unpackDepth(texture2D(uDepthBuffer,sampleTex))).z;
- // Add occlusion if checks succeed
- float bias = 1.0 / sampleRadius; // Bigger bias for smaller radius's (to fix artifacts)
- float depthCheck = (sampleDepth < samplePos.z - bias) ? 1.0 : 0.0;
- float rangeCheck = (abs(sampleDepth - origin.z) < sampleRadius) ? 1.0 : 0.0;
- occlusion += depthCheck * rangeCheck * uSSAOStrength;
- }
- // Invert and raise to power
- float power = uSSAOPower;
- float col = 1.0 - (occlusion / float(SAMPLES));
- col = pow(clamp(col, 0.0, 1.0), power);
- gl_FragColor = vec4(vec3(col), 1.0);
- }
- // Reconstruct Position From Depth
- /*vec3 reconstructPosition(vec2 texCoord) {
- // Calculate out of the fragment in screen space the view space position.
- float xx = texCoord.s * 2.0 - 1.0;
- float yy = texCoord.t * 2.0 - 1.0;
- float zz = unpackDepth(texture2D(uDepthBuffer, texCoord));
- vec4 posView = uProjMatrixInv * vec4(xx, yy, zz, 1.0);
- posView /= posView.w;
- return posView.xyz;
- }
- // Calculate SSAO
- void main() {
- // Information about the current screen-pixel
- float depth = unpackDepth(texture2D(uDepthBuffer, vTexCoord)) * uCamFar;
- vec3 depthPosition = reconstructPosition(vTexCoord);
- vec3 normal = unpackNormal(texture2D(uNormalBuffer, vTexCoord));
- // Calculate adjusted SSAO radius
- float offsetScale = uSSAORadius / depth;
- // Calculate Noise
- vec2 noiseScale = uScreenSize / 4.0;
- vec2 noiseVector = normalize(texture2D(uNoiseBuffer, vTexCoord * noiseScale).xy * 2.0 - 1.0);
- // Get Aspect Ratio
- float iAspectRatio = uScreenSize.y / uScreenSize.x;
- // Do the SSAO calculation
- float occlusion = 0.0;
- float samplesOccluded = 0.0;
- for (int i = 0; i < SAMPLES; i++) {
- // Get sample position
- vec2 offset = reflect(uSSAOKernel[i].xy, noiseVector) * offsetScale;
- offset.x *= iAspectRatio;
- vec2 sampleCoords = vTexCoord + offset;
- // Test if Samplecoords are inside the actual texture-range
- float TEXCHECK = (sampleCoords.x >= 0.0 && sampleCoords.x <= 1.0 && sampleCoords.y >= 0.0 && sampleCoords.y <= 1.0) ? 1.0 : 0.0;
- samplesOccluded += TEXCHECK;
- vec3 sample = reconstructPosition(sampleCoords);
- vec3 sampleNormal = unpackNormal(texture2D(uNormalBuffer, sampleCoords));
- // Calculate check variables
- vec3 normalDifference = sampleNormal - normal;
- float normalDot = dot(sampleNormal, normal);
- //float normalAngle =
- float normalCheck = abs(normalDifference.x) + abs(normalDifference.y) + abs(normalDifference.z);
- float depthCheck = (depthPosition.z >= sample.z) ? 1.0 : 0.0;
- float rangeCheck = (abs(depthPosition.z - sample.z) * uCamFar < uSSAORadius * 2.0) ? 1.0 : 0.0;
- // Calculate SSAO (Has to pass range-check, normal-check, and depth-check)
- occlusion += (rangeCheck * normalCheck * depthCheck) * uSSAOStrength * TEXCHECK;
- }
- // Invert SSAO
- occlusion = 1.0 - (occlusion / samplesOccluded);
- // Power
- float power = uSSAOPower;
- occlusion = pow(clamp(occlusion, 0.0, 1.0), power);
- // Send the final color
- gl_FragColor = vec4(occlusion, occlusion, occlusion, 1.0);
- }*/
Add Comment
Please, Sign In to add comment