adceccf402
Changed so that the picking pass get drawn once in the beginning so that the AO shatde could calculate AO from the depthbuffer generated during pthe pickingpass. In the ImGUI debugg window there is now sliders to change the behavior of the AO shader. Only the minimum ambient lightning is HardCoded in to the frowardPlus fragmentshaders with a define in the begining.
115 lines
3.8 KiB
GLSL
115 lines
3.8 KiB
GLSL
#version 430
|
|
|
|
//Number of samples per pixel
|
|
uniform int uNumOfSamples;
|
|
//#define NUM_SAMPLES (11)
|
|
|
|
//Number of turns around the cirle
|
|
uniform int uNumOfTurns;
|
|
//#define NUM_TURNS (7)
|
|
|
|
layout (binding = 0) uniform sampler2D ViewSpaceZ;
|
|
|
|
uniform vec4 uProjInfo;
|
|
|
|
uniform float uProjScale;
|
|
//#define ProjScale 500
|
|
|
|
uniform float uRadius;
|
|
//#define Radius 1.0f
|
|
|
|
uniform float uBias;
|
|
//#define Bias 0.012f
|
|
|
|
uniform float uContrast;
|
|
//#define IntensityDivR6 1
|
|
|
|
uniform float uIntensityScale;
|
|
|
|
out float AO;
|
|
|
|
vec3 getVSPosition(ivec2 ScreenSpaceCoord) {
|
|
float z = texelFetch(ViewSpaceZ, ScreenSpaceCoord, 0).r;
|
|
//Get the xy view space coordinates and add the z value from ViewSpaceZ buffer.
|
|
return vec3((uProjInfo[0] + (ScreenSpaceCoord.x * uProjInfo[1])) * z, (uProjInfo[2] + (ScreenSpaceCoord.y * uProjInfo[3])) * z, z);
|
|
}
|
|
|
|
vec3 getVSFaceNormal(vec3 ViewSpacePosition) {
|
|
// Get tangets vector for the plane and ViewSpacePositin... don't ask how this functions works. It's pure magic.
|
|
// They do this and it just works... I would guess that they approximate the function of a plane from pixels close to the pixel were on now.
|
|
return normalize(cross(dFdx(ViewSpacePosition), dFdy(ViewSpacePosition)));
|
|
}
|
|
|
|
|
|
vec3 getSampleViewSpacePos(ivec2 ScreenSpaceCoord, int SampleIndex, float RotationAngle, float ScreenSpaceSampleRadius){
|
|
// Pure Magic...
|
|
float alpha = float(SampleIndex) * (1.0 / uNumOfSamples);
|
|
|
|
// Angle to where to sample
|
|
float angle = alpha * (uNumOfTurns * 6.28) + RotationAngle;
|
|
|
|
//Lenght to were to sample
|
|
ScreenSpaceSampleRadius = ScreenSpaceSampleRadius * alpha;
|
|
|
|
vec2 screenSpaceSampleOffsetVecor = vec2(cos(angle), sin(angle));
|
|
|
|
// Get texel coordinate on where to sample by going screenSpaceSampleOffsetVecor direction in ScreenSpaceSampleRadius units from ScreenSpaceCoord (the point being shaded);
|
|
ivec2 screenSpaceSampleTexel = ivec2(ScreenSpaceSampleRadius * screenSpaceSampleOffsetVecor) + ScreenSpaceCoord;
|
|
|
|
return getVSPosition(screenSpaceSampleTexel);
|
|
}
|
|
|
|
|
|
|
|
float sampleAO(ivec2 ScreenSpaceCoord, vec3 Origin, vec3 OriginNormal, float ScreenSpaceSampleRadius, int SampleIndex, float RotationAngle, float Radius) {
|
|
float radius2 = Radius * Radius;
|
|
vec3 sampleViewSpacePosition = getSampleViewSpacePos(ScreenSpaceCoord, SampleIndex, RotationAngle, ScreenSpaceSampleRadius);
|
|
|
|
vec3 sampleVector = Origin - sampleViewSpacePosition;
|
|
|
|
// vv = sampleVectorLenght ^ 2
|
|
float vv = dot(sampleVector, sampleVector);
|
|
// vn = angle between sampleVector and Normal
|
|
float vn = dot(sampleVector, OriginNormal);
|
|
|
|
const float epsilon = 0.0001f;
|
|
|
|
// vv < radius2 if the vector is shorter then the radius;
|
|
// vn - bias, offset the angle to reduse self occlusion.
|
|
// epsilon is here to make divison by 0 impossible.
|
|
return float(vv < radius2) * max((vn - uBias) / (epsilon + vv), 0.0);
|
|
//float f = max(radius2 - vv, 0.0);
|
|
//return f * f * f * max((vn - uBias) / (epsilon + vv), 0.0);
|
|
}
|
|
|
|
|
|
void main() {
|
|
ivec2 originScreenCoord = ivec2(gl_FragCoord.xy);
|
|
|
|
vec3 origin = getVSPosition(originScreenCoord);
|
|
|
|
float radius;
|
|
if(origin.z < uRadius){
|
|
radius = origin.z;
|
|
} else {
|
|
radius = uRadius;
|
|
}
|
|
|
|
|
|
vec3 originNormal = getVSFaceNormal(origin);
|
|
|
|
float screenSpaceSampleRadius = -uProjScale * radius / origin.z;
|
|
|
|
float rotationAngleOffset = 30 * originScreenCoord.x ^ originScreenCoord.y + 10 * originScreenCoord.x * originScreenCoord.y;
|
|
|
|
float sum = 0.0;
|
|
for (int i = 0; i < uNumOfSamples; i++) {
|
|
sum += sampleAO(originScreenCoord, origin, originNormal, screenSpaceSampleRadius, i, rotationAngleOffset, radius);
|
|
}
|
|
|
|
//float A = max(0.0, 1.0 - sum * (2.0f / uNumOfSamples));
|
|
float A = 1.0 - sum * (2.0f * uIntensityScale / float(uNumOfSamples));
|
|
AO = clamp(pow(A, uContrast), 0.0f, 1.0f);
|
|
//AO = vec4(originNormal, 1.0f);
|
|
}
|