mirror of
https://github.com/overte-org/overte.git
synced 2025-08-16 13:11:37 +02:00
161 lines
5.7 KiB
Text
161 lines
5.7 KiB
Text
<@include gpu/Config.slh@>
|
|
<$VERSION_HEADER$>
|
|
// Generated on <$_SCRIBE_DATE$>
|
|
//
|
|
// Created by Sam Gateau on 1/1/16.
|
|
// Copyright 2016 High Fidelity, Inc.
|
|
//
|
|
// Distributed under the Apache License, Version 2.0.
|
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
//
|
|
|
|
<@include ssao.slh@>
|
|
<$declareAmbientOcclusion()$>
|
|
<$declarePackOcclusionDepth()$>
|
|
|
|
|
|
const int LOG_MAX_OFFSET = 3;
|
|
const int MAX_MIP_LEVEL = 5;
|
|
|
|
// the depth pyramid texture
|
|
uniform sampler2D pyramidMap;
|
|
|
|
float getZEye(ivec2 pixel) {
|
|
return -texelFetch(pyramidMap, pixel, getResolutionLevel()).x;
|
|
}
|
|
|
|
vec3 evalEyePositionFromZeye(int side, float Zeye, vec2 texcoord) {
|
|
// compute the view space position using the depth
|
|
// basically manually pick the proj matrix components to do the inverse
|
|
float Xe = (-Zeye * (texcoord.x * 2.0 - 1.0) - Zeye * frameTransform._projection[side][2][0] - frameTransform._projection[side][3][0]) / frameTransform._projection[side][0][0];
|
|
float Ye = (-Zeye * (texcoord.y * 2.0 - 1.0) - Zeye * frameTransform._projection[side][2][1] - frameTransform._projection[side][3][1]) / frameTransform._projection[side][1][1];
|
|
return vec3(Xe, Ye, Zeye);
|
|
}
|
|
|
|
out vec4 outFragColor;
|
|
|
|
uniform sampler2D normalMap;
|
|
|
|
float getAngleDithering(in ivec2 pixelPos) {
|
|
// Hash function used in the AlchemyAO paper
|
|
return isDitheringEnabled() * (3 * pixelPos.x ^ pixelPos.y + pixelPos.x * pixelPos.y) * 10 + getFrameDithering();
|
|
}
|
|
|
|
const float TWO_PI = 6.28;
|
|
|
|
vec2 tapLocation(int sampleNumber, float spinAngle, out float ssR){
|
|
// Radius relative to ssR
|
|
float alpha = float(sampleNumber + 0.5) * getInvNumSamples();
|
|
float angle = alpha * (getNumSpiralTurns() * TWO_PI) + spinAngle;
|
|
|
|
ssR = alpha;
|
|
return vec2(cos(angle), sin(angle));
|
|
}
|
|
|
|
vec3 getOffsetPosition(ivec3 side, ivec2 ssC, vec2 unitOffset, float ssR) {
|
|
// Derivation:
|
|
// mipLevel = floor(log(ssR / MAX_OFFSET));
|
|
int mipLevel = clamp(findMSB(int(ssR)) - LOG_MAX_OFFSET, 0, MAX_MIP_LEVEL);
|
|
|
|
ivec2 ssOffset = ivec2(ssR * unitOffset);
|
|
ivec2 ssP = ssOffset + ssC;
|
|
if (bool(isBorderingEnabled())) {
|
|
ssP.x = ((ssP.x < 0 || ssP.x >= side.z) ? ssC.x - ssOffset.x : ssP.x);
|
|
ssP.y = ((ssP.y < 0 || ssP.y >= int(getWidthHeight().y)) ? ssC.y - ssOffset.y : ssP.y);
|
|
}
|
|
|
|
ivec2 ssPFull = ivec2(ssP.x + side.y, ssP.y);
|
|
|
|
vec3 P;
|
|
|
|
// We need to divide by 2^mipLevel to read the appropriately scaled coordinate from a MIP-map.
|
|
// Manually clamp to the texture size because texelFetch bypasses the texture unit
|
|
ivec2 mipP = clamp(ssPFull >> mipLevel, ivec2(0), textureSize(pyramidMap, getResolutionLevel() + mipLevel) - ivec2(1));
|
|
P.z = -texelFetch(pyramidMap, mipP, getResolutionLevel() + mipLevel).r;
|
|
|
|
// Offset to pixel center
|
|
vec2 tapUV = (vec2(ssP) + vec2(0.5)) / float(side.z);
|
|
P = evalEyePositionFromZeye(side.x, P.z, tapUV);
|
|
return P;
|
|
}
|
|
|
|
float sampleAO(in ivec3 side, in ivec2 ssC, in vec3 C, in vec3 n_C, in float ssDiskRadius, in int tapIndex, in float randomPatternRotationAngle) {
|
|
// Offset on the unit disk, spun for this pixel
|
|
float ssR;
|
|
vec2 unitOffset = tapLocation(tapIndex, randomPatternRotationAngle, ssR);
|
|
ssR *= ssDiskRadius;
|
|
|
|
|
|
|
|
// The occluding point in camera space
|
|
vec3 Q = getOffsetPosition(side, ssC, unitOffset, ssR);
|
|
|
|
vec3 v = Q - C;
|
|
float vv = dot(v, v);
|
|
float vn = dot(v, n_C);
|
|
|
|
// Fall off function as recommended in SAO paper
|
|
const float epsilon = 0.01;
|
|
float f = max(getRadius2() - vv, 0.0);
|
|
return f * f * f * max((vn - getFalloffBias()) / (epsilon + vv), 0.0);
|
|
}
|
|
|
|
void main(void) {
|
|
// Pixel being shaded
|
|
ivec2 ssC = ivec2(gl_FragCoord.xy);
|
|
|
|
// Fetch the z under the pixel (stereo or not)
|
|
float Zeye = getZEye(ssC);
|
|
|
|
// Stereo side info
|
|
ivec3 side = getStereoSideInfo(ssC.x);
|
|
|
|
// From now on, ssC is the pixel pos in the side
|
|
ssC.x -= side.y;
|
|
vec2 fragPos = (vec2(ssC) + 0.5) / getStereoSideWidth();
|
|
|
|
// The position and normal of the pixel fragment in Eye space
|
|
vec3 Cp = evalEyePositionFromZeye(side.x, Zeye, fragPos);
|
|
vec3 Cn = evalEyeNormal(Cp);
|
|
|
|
// Choose the screen-space sample radius
|
|
// proportional to the projected area of the sphere
|
|
float ssDiskRadius = -getProjScale() * getRadius() / Cp.z;
|
|
|
|
// Let's make noise
|
|
float randomPatternRotationAngle = getAngleDithering(ssC);
|
|
|
|
// Accumulate the Obscurance for each samples
|
|
float sum = 0.0;
|
|
for (int i = 0; i < getNumSamples(); ++i) {
|
|
sum += sampleAO(side, ssC, Cp, Cn, ssDiskRadius, i, randomPatternRotationAngle);
|
|
}
|
|
|
|
float A = max(0.0, 1.0 - sum * getObscuranceScaling() * 5.0 * getInvNumSamples());
|
|
|
|
<! // KEEP IT for Debugging
|
|
// Bilateral box-filter over a quad for free, respecting depth edges
|
|
// (the difference that this makes is subtle)
|
|
if (abs(dFdx(Cp.z)) < 0.02) {
|
|
A -= dFdx(A) * ((ssC.x & 1) - 0.5);
|
|
}
|
|
if (abs(dFdy(Cp.z)) < 0.02) {
|
|
A -= dFdy(A) * ((ssC.y & 1) - 0.5);
|
|
}
|
|
!>
|
|
|
|
outFragColor = vec4(packOcclusionDepth(A, CSZToDephtKey(Cp.z)), 1.0);
|
|
|
|
<! // KEEP IT for Debugging
|
|
// Debug Normal: outFragColor = vec4((Cn + vec3(1.0))* 0.5, 1.0);
|
|
// Debug Radius outFragColor = vec4(vec3(ssDiskRadius / 100.0), 1.0);
|
|
// Debug MaxMiplevel outFragColor = vec4(1.0 - vec3(float(clamp(findMSB(int(ssDiskRadius)) - LOG_MAX_OFFSET, 0, MAX_MIP_LEVEL))/ float(MAX_MIP_LEVEL)), 1.0);
|
|
// Debug OffsetPosition
|
|
float ssR;
|
|
vec2 unitOffset = tapLocation(int(getNumSamples() - 1), 0, ssR);
|
|
vec3 Q = getOffsetPosition(side, ssC, unitOffset, ssR * ssDiskRadius);
|
|
//outFragColor = vec4(vec3(Q.x / 10.0, Q.y / 2.0, -Q.z/ 3.0), 1.0);
|
|
vec3 v = normalize(Q - Cp);
|
|
outFragColor = vec4((v + vec3(1.0))* 0.5, 1.0);
|
|
!>
|
|
}
|