townforge/GameData/Shaders/GLSL/SSAO.glsl
2022-01-19 16:42:25 -03:00

155 lines
5.1 KiB
GLSL
Executable File

// MIT License
// Copyright (c) 2020 Arnis Lielturks
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include "Uniforms.glsl"
#include "Samplers.glsl"
#include "Transform.glsl"
#include "ScreenPos.glsl"
#include "PostProcess.glsl"
varying vec2 vTexCoord;
#ifdef COMPILEPS
uniform vec2 cSSAOInvSize;
uniform vec2 cBlurHInvSize;
uniform vec2 cBlurVInvSize;
uniform float cSSAOStrength;
uniform float cSSAORadius;
uniform float cSSAOBase;
uniform float cSSAOArea;
uniform float cSSAOFalloff;
uniform float cSSAONoiseFactor;
#endif
void VS()
{
mat4 modelMatrix = iModelMatrix;
vec3 worldPos = GetWorldPos(modelMatrix);
gl_Position = GetClipPos(worldPos);
vTexCoord = GetQuadTexCoord(gl_Position);
}
#ifdef COMPILEPS
vec3 normalFromDepth(float depth, vec2 texcoords)
{
vec2 offset1 = vec2(0.0, cSSAOInvSize.y);
vec2 offset2 = vec2(cSSAOInvSize.x, 0.0);
float depth1 = DecodeDepth(texture2D(sDepthBuffer, texcoords + offset1).rgb) * cFarClipPS;
float depth2 = DecodeDepth(texture2D(sDepthBuffer, texcoords + offset2).rgb) * cFarClipPS;
vec3 p1 = vec3(offset1, depth1 - depth);
vec3 p2 = vec3(offset2, depth2 - depth);
vec3 normal = cross(p1, p2);
return normalize(normal);
}
vec3 reflection(vec3 v1,vec3 v2)
{
vec3 result = 2.0 * dot(v2, v1) * v2;
result = v1 - result;
return result;
}
#endif
void PS()
{
#ifdef OCCLUDE
//Edge Mask
//float edge = min( min( vTexCoord.x, 1.0 - vTexCoord.x ), min( vTexCoord.y, 1.0 - vTexCoord.y ) );
//edge = clamp( 2 * edge + 0.001, 0.8, 1.0);
float depth = DecodeDepth(texture2D(sDepthBuffer, vTexCoord).rgb) * cFarClipPS;
if( depth >= 1000.0) {
gl_FragColor = vec4(1.0);
return;
}
vec3 sample_sphere[16] = vec3[](
vec3( 0.5381, 0.1856,-0.4319), vec3( 0.1379, 0.2486, 0.4430),
vec3( 0.3371, 0.5679,-0.0057), vec3(-0.6999,-0.0451,-0.0019),
vec3( 0.0689,-0.1598,-0.8547), vec3( 0.0560, 0.0069,-0.1843),
vec3(-0.0146, 0.1402, 0.0762), vec3( 0.0100,-0.1924,-0.0344),
vec3(-0.3577,-0.5301,-0.4358), vec3(-0.3169, 0.1063, 0.0158),
vec3( 0.0103,-0.5869, 0.0046), vec3(-0.0897,-0.4940, 0.3287),
vec3( 0.7119,-0.0154,-0.0918), vec3(-0.0533, 0.0596,-0.5411),
vec3( 0.0352,-0.0631, 0.5460), vec3(-0.4776, 0.2847,-0.0271)
);
vec3 random = normalize( texture2D(sDiffMap, vTexCoord * cSSAONoiseFactor).rgb );
vec3 position = vec3(vTexCoord.x, vTexCoord.y,depth);
vec3 normal = normalFromDepth(depth, vTexCoord);
//AO Radius based on distance
float radiusDepth = cSSAORadius / depth;
float occlusion = 0.0;
int iterations = 8; // 8 More noise / Better performance
for (int j = 0; j < iterations; ++j)
{
vec3 ray = radiusDepth * reflection(sample_sphere[j], random);
vec3 hemiRay = position + sign(dot(ray, normal)) * ray;
//Fix Distance of SSAO
float occDepth = DecodeDepth(texture2D(sDepthBuffer, clamp(hemiRay.xy, 0.0, 1.0)).rgb) * cFarClipPS;
float difference = depth - occDepth * 1.0015;
occlusion += step(cSSAOFalloff, difference) * (1.0 - smoothstep(cSSAOFalloff, cSSAOArea, difference));
}
//AO intensity based on distance
float aoDepthInt = mix(0.5, 0.8, depth * 0.02) * mix(1.0, 0.0, depth * 0.001);
float ao = 1.0 - (cSSAOStrength * aoDepthInt) * occlusion * (1.0 / iterations);
float final = clamp(ao + cSSAOBase, 0.0, 1.0);
gl_FragColor = vec4(vec3(final), 1.0);
#endif
#ifdef BLURV
gl_FragColor = GaussianBlur(3, vec2(0.0, 1.0), cBlurVInvSize * 2.0, 2.0, sDiffMap, vTexCoord);
#endif
#ifdef BLURH
gl_FragColor = GaussianBlur(3, vec2(1.0, 0.0), cBlurHInvSize * 2.0, 2.0, sDiffMap, vTexCoord);
#endif
#ifdef OUTPUT
gl_FragColor.rgb = texture2D(sDiffMap, vTexCoord).rgb * texture2D(sDepthBuffer, vTexCoord).rgb;
// gl_FragColor.rgb = texture2D(sDepthBuffer, vTexCoord).rgb;
// if (vTexCoord.x > 0.5) {
// gl_FragColor.rgb = texture2D(sDiffMap, vTexCoord).rgb * texture2D(sDepthBuffer, vTexCoord).rgb;
// }
// else
// {
// gl_FragColor.rgb = texture2D(sDepthBuffer, vTexCoord).rgb;
// }
#endif
}