summaryrefslogtreecommitdiffstats
path: root/res/effectlib/screenSpaceAO.glsllib
diff options
context:
space:
mode:
Diffstat (limited to 'res/effectlib/screenSpaceAO.glsllib')
-rw-r--r--res/effectlib/screenSpaceAO.glsllib150
1 files changed, 150 insertions, 0 deletions
diff --git a/res/effectlib/screenSpaceAO.glsllib b/res/effectlib/screenSpaceAO.glsllib
new file mode 100644
index 0000000..54204a1
--- /dev/null
+++ b/res/effectlib/screenSpaceAO.glsllib
@@ -0,0 +1,150 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SCREEN_SPACE_AO_GLSLLIB
+#define SCREEN_SPACE_AO_GLSLLIB 1
+
+#include "depthpass.glsllib"
+
+
+float hashRot(vec2 pos)
+{
+ // Basically an odd-even hash.
+ float px = 2.0 * fract(floor(pos.x) * 0.5);
+ float py = fract(floor(pos.y) * 0.5);
+
+ return px + py;
+}
+
+vec3 quatRotate( vec4 q, vec3 v )
+{
+ return v + 2.0 * cross( cross( v, q.xyz ) + q.w * v, q.xyz );
+}
+
+vec3 getViewSpacePos( sampler2D depthSampler, vec2 camProps, vec2 UV, vec4 UvToEye )
+{
+ float sampleDepth = getDepthValue( texture(depthSampler, UV), camProps );
+ sampleDepth = depthValueToLinearDistance( sampleDepth, camProps );
+
+ vec2 scaledUV = (UV * UvToEye.xy) + UvToEye.zw;
+ return vec3(scaledUV * sampleDepth, sampleDepth);
+}
+
+vec2 computeDir( vec2 baseDir, int v )
+{
+ float ang = 3.1415926535 * hashRot( gl_FragCoord.xy ) + float(v - 1);
+ vec2 vX = vec2(cos(ang), sin(ang));
+ vec2 vY = vec2(-sin(ang), cos(ang));
+
+ return vec2( dot(baseDir, vX), dot(baseDir, vY) );
+}
+
+vec2 offsetDir( vec2 baseDir, int v )
+{
+ float ang = float(v - 1);
+ vec2 vX = vec2(cos(ang), sin(ang));
+ vec2 vY = vec2(-sin(ang), cos(ang));
+
+ return vec2( dot(baseDir, vX), dot(baseDir, vY) );
+}
+
+float SSambientOcclusion(sampler2D depthSampler, vec3 viewNorm, vec4 aoParams, vec4 aoParams2, vec2 camProps, vec4 aoScreen, vec4 UvToEye)
+{
+ float ret = 0.0;
+
+ vec2 centerUV = gl_FragCoord.xy * aoScreen.zw;
+ vec3 viewPos = getViewSpacePos( depthSampler, camProps, centerUV, UvToEye );
+ viewPos += viewNorm * aoParams.w;
+
+ float screenRadius = aoParams.y * aoScreen.y / viewPos.z;
+ if (screenRadius < 1.0) { return 1.0; }
+
+ vec3 kernel[9];
+
+ // The X and Y are the 2d direction, while the Z is the height of the sphere at that point.
+ // In essence, it normalizes the 3d vector, but we're really interested in the 2D offset.
+ kernel[0] = vec3(-0.1376476, 0.2842022, 0.948832);
+ kernel[1] = vec3(-0.626618, 0.4594115, 0.629516);
+ kernel[2] = vec3(-0.8903138, -0.05865424, 0.451554);
+ kernel[3] = vec3(0.2871419, 0.8511679, 0.439389);
+ kernel[4] = vec3(-0.1525251, -0.3870117, 0.909372);
+ kernel[5] = vec3(0.6978705, -0.2176773, 0.682344);
+ kernel[6] = vec3(0.7343006, 0.3774331, 0.5642);
+ kernel[7] = vec3(0.1408805, -0.88915, 0.4353);
+ kernel[8] = vec3(-0.6642616, -0.543601, 0.5130);
+
+ int radLevels = int(floor(aoParams2.x));
+ float radStep = 1.0 / aoParams2.x;
+
+ for (int j = 1; j <= radLevels; ++j)
+ {
+ for (int i = 0; i < 9; ++i)
+ {
+ float curRange = aoParams.y * radStep * float(j);
+ float curRadius = curRange * kernel[i].z;
+
+ vec3 smpDir;
+ smpDir.xy = computeDir(kernel[i].xy, j) * aoParams2.y + (1.0 - aoParams2.y) * offsetDir(kernel[i].xy, j);
+ smpDir.z = kernel[i].z;
+ smpDir *= curRange;
+
+ vec2 smpUV = centerUV.xy + smpDir.xy * aoScreen.zw;
+
+ // First method is based on Horizon-Based AO
+ vec3 samplePos = getViewSpacePos( depthSampler, camProps, smpUV, UvToEye );
+ vec3 smpVec = samplePos - viewPos;
+
+ float lenRad = dot(smpVec, smpVec);
+ smpVec = normalize(smpVec);
+ float lenDot = dot(smpVec, viewNorm);
+
+ lenRad /= aoParams.y*aoParams.y;
+ float falloff = smoothstep(8.0, 0.0, (lenRad - 1.0) * 0.125);
+ float occl = 1.0 - clamp(lenDot * falloff, 0.0, 1.0);
+
+ ret += occl * occl;
+ }
+ }
+
+ ret = (ret) / (9.0 * float(radLevels));
+
+ // Blend between soft and hard based on softness param
+ // NOTE : the 0.72974 is actually an gamma-inverted 0.5 (assuming gamma 2.2)
+ // Would not need this if we linearized color instead.
+ float hardCut = (1.0 - aoParams.z) * 0.72974;
+ ret = smoothstep(0.0, 1.0, (ret - hardCut) / (1.0 - hardCut));
+
+ // Blend between full and no occlusion based on strength param
+ ret = aoParams.x * ret + (1.0 - aoParams.x);
+
+ return ret;
+}
+
+#endif