Improving readability in shader

This commit is contained in:
Christopher Root 2015-08-15 14:40:34 -07:00
parent 8ea6048ec7
commit 21dc58eb85

View file

@ -103,95 +103,94 @@ vec3 UVToViewSpace(vec2 uv, float z){
* The depth of the uv coord is determined from the depth texture.
* uv: the uv coordinates to convert
*/
vec3 GetViewPos(vec2 uv){
vec3 GetViewPos(vec2 uv) {
float z = ViewSpaceZFromDepth(texture(depthTexture, uv).r);
return UVToViewSpace(uv, z);
}
float TanToSin(float x){
return x * inversesqrt(x*x + 1.0);
float TanToSin(float x) {
return x * inversesqrt(x*x + 1.0);
}
float InvLength(vec2 V){
return inversesqrt(dot(V,V));
float InvLength(vec2 V) {
return inversesqrt(dot(V, V));
}
float Tangent(vec3 V){
return V.z * InvLength(V.xy);
float Tangent(vec3 V) {
return V.z * InvLength(V.xy);
}
float BiasedTangent(vec3 V){
return V.z * InvLength(V.xy) + TanBias;
float BiasedTangent(vec3 V) {
return V.z * InvLength(V.xy) + TanBias;
}
float Tangent(vec3 P, vec3 S){
float Tangent(vec3 P, vec3 S) {
return -(P.z - S.z) * InvLength(S.xy - P.xy);
}
float Length2(vec3 V){
return dot(V,V);
float Length2(vec3 V) {
return dot(V, V);
}
vec3 MinDiff(vec3 P, vec3 Pr, vec3 Pl){
vec3 MinDiff(vec3 P, vec3 Pr, vec3 Pl) {
vec3 V1 = Pr - P;
vec3 V2 = P - Pl;
return (Length2(V1) < Length2(V2)) ? V1 : V2;
}
vec2 SnapUVOffset(vec2 uv){
// return round(uv * AORes) * InvAORes;
vec2 SnapUVOffset(vec2 uv) {
return round(uv * renderTargetRes) * renderTargetResInv;
}
float Falloff(float d2){
return d2 * NegInvR2 + 1.0f;
float Falloff(float d2) {
return d2 * NegInvR2 + 1.0f;
}
float HorizonOcclusion( vec2 deltaUV, vec3 P, vec3 dPdu, vec3 dPdv, float randstep, float numSamples){
float ao = 0;
float HorizonOcclusion(vec2 deltaUV, vec3 P, vec3 dPdu, vec3 dPdv, float randstep, float numSamples) {
float ao = 0;
// Offset the first coord with some noise
vec2 uv = varTexcoord + SnapUVOffset(randstep*deltaUV);
deltaUV = SnapUVOffset( deltaUV );
// Offset the first coord with some noise
vec2 uv = varTexcoord + SnapUVOffset(randstep*deltaUV);
deltaUV = SnapUVOffset(deltaUV);
// Calculate the tangent vector
vec3 T = deltaUV.x * dPdu + deltaUV.y * dPdv;
// Calculate the tangent vector
vec3 T = deltaUV.x * dPdu + deltaUV.y * dPdv;
// Get the angle of the tangent vector from the viewspace axis
float tanH = BiasedTangent(T);
float sinH = TanToSin(tanH);
// Get the angle of the tangent vector from the viewspace axis
float tanH = BiasedTangent(T);
float sinH = TanToSin(tanH);
float tanS;
float d2;
vec3 S;
float tanS;
float d2;
vec3 S;
// Sample to find the maximum angle
for(float s = 1; s <= numSamples; ++s){
uv += deltaUV;
S = GetViewPos(uv);
tanS = Tangent(P, S);
d2 = Length2(S - P);
// Sample to find the maximum angle
for (float s = 1; s <= numSamples; ++s) {
uv += deltaUV;
S = GetViewPos(uv);
tanS = Tangent(P, S);
d2 = Length2(S - P);
// Is the sample within the radius and the angle greater?
if(d2 < R2 && tanS > tanH)
{
float sinS = TanToSin(tanS);
// Apply falloff based on the distance
ao += Falloff(d2) * (sinS - sinH);
// Is the sample within the radius and the angle greater?
if (d2 < R2 && tanS > tanH) {
float sinS = TanToSin(tanS);
// Apply falloff based on the distance
ao += Falloff(d2) * (sinS - sinH);
tanH = tanS;
sinH = sinS;
}
}
return ao;
tanH = tanS;
sinH = sinS;
}
}
return ao;
}
vec2 RotateDirections(vec2 Dir, vec2 CosSin){
return vec2(Dir.x*CosSin.x - Dir.y*CosSin.y, Dir.x*CosSin.y + Dir.y*CosSin.x);
vec2 RotateDirections(vec2 Dir, vec2 CosSin) {
return vec2(Dir.x*CosSin.x - Dir.y*CosSin.y,
Dir.x*CosSin.y + Dir.y*CosSin.x);
}
void ComputeSteps(inout vec2 stepSizeUv, inout float numSteps, float rayRadiusPix, float rand){
void ComputeSteps(inout vec2 stepSizeUv, inout float numSteps, float rayRadiusPix, float rand) {
// Avoid oversampling if numSteps is greater than the kernel radius in pixels
numSteps = min(NumSamples, rayRadiusPix);
@ -200,8 +199,7 @@ void ComputeSteps(inout vec2 stepSizeUv, inout float numSteps, float rayRadiusPi
// Clamp numSteps if it is greater than the max kernel footprint
float maxNumSteps = MaxRadiusPixels / stepSizePix;
if (maxNumSteps < numSteps)
{
if (maxNumSteps < numSteps) {
// Use dithering to avoid AO discontinuities
numSteps = floor(maxNumSteps + rand);
numSteps = max(numSteps, 1);
@ -209,23 +207,22 @@ void ComputeSteps(inout vec2 stepSizeUv, inout float numSteps, float rayRadiusPi
}
// Step size in uv space
// stepSizeUv = stepSizePix * InvAORes;
stepSizeUv = stepSizePix * renderTargetResInv;
}
float getRandom(vec2 uv){
float getRandom(vec2 uv) {
return fract(sin(dot(uv.xy ,vec2(12.9898,78.233))) * 43758.5453);
}
void main(void){
void main(void) {
mat4 projMatrix = getTransformCamera()._projection;
float numDirections = NumDirections;
float numDirections = NumDirections;
vec3 P, Pr, Pl, Pt, Pb;
P = GetViewPos(varTexcoord);
vec3 P, Pr, Pl, Pt, Pb;
P = GetViewPos(varTexcoord);
// Sample neighboring pixels
// Sample neighboring pixels
Pr = GetViewPos(varTexcoord + vec2( renderTargetResInv.x, 0));
Pl = GetViewPos(varTexcoord + vec2(-renderTargetResInv.x, 0));
Pt = GetViewPos(varTexcoord + vec2( 0, renderTargetResInv.y));
@ -236,9 +233,9 @@ void main(void){
vec3 dPdv = MinDiff(P, Pt, Pb) * (renderTargetRes.y * renderTargetResInv.x);
// Get the random samples from the noise function
vec3 random = vec3(getRandom(varTexcoord.xy), getRandom(varTexcoord.yx), getRandom(varTexcoord.xx));
vec3 random = vec3(getRandom(varTexcoord.xy), getRandom(varTexcoord.yx), getRandom(varTexcoord.xx));
// Calculate the projected size of the hemisphere
// Calculate the projected size of the hemisphere
float w = P.z * projMatrix[2][3] + projMatrix[3][3];
vec2 rayRadiusUV = (0.5 * R * vec2(projMatrix[0][0], projMatrix[1][1]) / w); // [-1,1] -> [0,1] uv
float rayRadiusPix = rayRadiusUV.x * renderTargetRes.x;
@ -246,36 +243,36 @@ void main(void){
float ao = 1.0;
// Make sure the radius of the evaluated hemisphere is more than a pixel
if(rayRadiusPix > 1.0){
ao = 0.0;
float numSteps;
vec2 stepSizeUV;
if(rayRadiusPix > 1.0) {
ao = 0.0;
float numSteps;
vec2 stepSizeUV;
// Compute the number of steps
ComputeSteps(stepSizeUV, numSteps, rayRadiusPix, random.z);
// Compute the number of steps
ComputeSteps(stepSizeUV, numSteps, rayRadiusPix, random.z);
float alpha = 2.0 * PI / numDirections;
float alpha = 2.0 * PI / numDirections;
// Calculate the horizon occlusion of each direction
for(float d = 0; d < numDirections; ++d){
float theta = alpha * d;
// Calculate the horizon occlusion of each direction
for(float d = 0; d < numDirections; ++d) {
float theta = alpha * d;
// Apply noise to the direction
vec2 dir = RotateDirections(vec2(cos(theta), sin(theta)), random.xy);
vec2 deltaUV = dir * stepSizeUV;
// Apply noise to the direction
vec2 dir = RotateDirections(vec2(cos(theta), sin(theta)), random.xy);
vec2 deltaUV = dir * stepSizeUV;
// Sample the pixels along the direction
ao += HorizonOcclusion( deltaUV,
P,
dPdu,
dPdv,
random.z,
numSteps);
}
// Sample the pixels along the direction
ao += HorizonOcclusion( deltaUV,
P,
dPdu,
dPdv,
random.z,
numSteps);
}
// Average the results and produce the final AO
ao = 1.0 - ao / numDirections * AOStrength;
}
// Average the results and produce the final AO
ao = 1.0 - ao / numDirections * AOStrength;
}
outFragColor = vec4(vec3(ao), 1.0);