add SSAO
This commit is contained in:
+4
-6
@@ -33,10 +33,7 @@ import com.seibel.distanthorizons.core.util.math.Vec3d;
|
||||
import com.seibel.distanthorizons.core.util.objects.SortedArraySet;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.render.IMcGenericRenderer;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.render.IMcLodRenderer;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.render.IMcTestRenderer;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.render.IVertexBufferWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.render.*;
|
||||
import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector;
|
||||
import com.seibel.distanthorizons.core.util.math.Vec3f;
|
||||
|
||||
@@ -150,6 +147,7 @@ public class McLodRenderer
|
||||
}
|
||||
|
||||
IMcLodRenderer lodRenderer = SingletonInjector.INSTANCE.get(IMcLodRenderer.class);
|
||||
IMcSsaoRenderer ssaoRenderer = SingletonInjector.INSTANCE.get(IMcSsaoRenderer.class);
|
||||
|
||||
|
||||
|
||||
@@ -183,8 +181,8 @@ public class McLodRenderer
|
||||
// SSAO
|
||||
if (Config.Client.Advanced.Graphics.Ssao.enableSsao.get())
|
||||
{
|
||||
//profiler.popPush("LOD SSAO");
|
||||
//SSAORenderer.INSTANCE.render(new Mat4f(renderParams.dhProjectionMatrix), renderParams.partialTicks);
|
||||
profiler.popPush("LOD SSAO");
|
||||
ssaoRenderer.render(renderParams.dhProjectionMatrix);
|
||||
}
|
||||
|
||||
// custom objects without SSAO
|
||||
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.distanthorizons.core.wrapperInterfaces.render;
|
||||
|
||||
import com.seibel.distanthorizons.api.objects.math.DhApiMat4f;
|
||||
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||
import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IBindable;
|
||||
|
||||
public interface IMcSsaoRenderer extends IBindable
|
||||
{
|
||||
|
||||
void render(DhApiMat4f dhProjectionMatrix);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
#version 150 core
|
||||
#extension GL_ARB_derivative_control : enable
|
||||
|
||||
#define SAMPLE_MAX 64
|
||||
|
||||
#define saturate(x) (clamp((x), 0.0, 1.0))
|
||||
|
||||
in vec2 TexCoord;
|
||||
|
||||
out vec4 fragColor;
|
||||
|
||||
|
||||
layout (std140) uniform fragUniformBlock
|
||||
{
|
||||
int uSampleCount;
|
||||
|
||||
float uRadius;
|
||||
float uStrength;
|
||||
float uMinLight;
|
||||
float uBias;
|
||||
float uFadeDistanceInBlocks;
|
||||
|
||||
mat4 uInvProj;
|
||||
mat4 uProj;
|
||||
};
|
||||
|
||||
uniform sampler2D uDhDepthTexture;
|
||||
|
||||
const float EPSILON = 1.e-6;
|
||||
const float GOLDEN_ANGLE = 2.39996323;
|
||||
const vec3 MAGIC = vec3(0.06711056, 0.00583715, 52.9829189);
|
||||
const float PI = 3.1415926538;
|
||||
const float TAU = PI * 2.0;
|
||||
|
||||
|
||||
vec3 unproject(vec4 pos)
|
||||
{
|
||||
return pos.xyz / pos.w;
|
||||
}
|
||||
|
||||
float InterleavedGradientNoise(const in vec2 pixel)
|
||||
{
|
||||
float x = dot(pixel, MAGIC.xy);
|
||||
return fract(MAGIC.z * fract(x));
|
||||
}
|
||||
|
||||
vec3 calcViewPosition(const in vec3 clipPos)
|
||||
{
|
||||
vec4 viewPos = uInvProj * vec4(clipPos * 2.0 - 1.0, 1.0);
|
||||
return viewPos.xyz / viewPos.w;
|
||||
}
|
||||
|
||||
float GetSpiralOcclusion(const in vec2 uv, const in vec3 viewPos, const in vec3 viewNormal)
|
||||
{
|
||||
float dither = InterleavedGradientNoise(gl_FragCoord.xy);
|
||||
float rotatePhase = dither * TAU;
|
||||
float rStep = uRadius / uSampleCount;
|
||||
|
||||
vec2 offset;
|
||||
|
||||
float ao = 0.0;
|
||||
int sampleCount = 0;
|
||||
float radius = rStep;
|
||||
for (int i = 0; i < clamp(uSampleCount, 1, SAMPLE_MAX); i++) {
|
||||
vec2 offset = vec2(
|
||||
sin(rotatePhase),
|
||||
cos(rotatePhase)
|
||||
) * radius;
|
||||
|
||||
radius += rStep;
|
||||
rotatePhase += GOLDEN_ANGLE;
|
||||
|
||||
vec3 sampleViewPos = viewPos + vec3(offset, -0.1);
|
||||
vec3 sampleClipPos = unproject(uProj * vec4(sampleViewPos, 1.0)) * 0.5 + 0.5;
|
||||
sampleClipPos = saturate(sampleClipPos);
|
||||
|
||||
float sampleClipDepth = textureLod(uDhDepthTexture, sampleClipPos.xy, 0.0).r;
|
||||
if (sampleClipDepth >= 1.0 - EPSILON) continue;
|
||||
|
||||
sampleClipPos.z = sampleClipDepth;
|
||||
sampleViewPos = unproject(uInvProj * vec4(sampleClipPos * 2.0 - 1.0, 1.0));
|
||||
|
||||
vec3 diff = sampleViewPos - viewPos;
|
||||
float sampleDist = length(diff);
|
||||
vec3 sampleNormal = diff / sampleDist;
|
||||
|
||||
float sampleNoLm = max(dot(viewNormal, sampleNormal) - uBias, 0.0);
|
||||
float aoF = 1.0 - saturate(sampleDist / uRadius);
|
||||
ao += sampleNoLm * aoF;
|
||||
sampleCount++;
|
||||
}
|
||||
|
||||
ao /= max(sampleCount, 1);
|
||||
ao = smoothstep(0.0, uStrength, ao);
|
||||
|
||||
return ao * (1.0 - uMinLight);
|
||||
}
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
float fragmentDepth = textureLod(uDhDepthTexture, TexCoord, 0).r;
|
||||
float occlusion = 0.0;
|
||||
|
||||
// Do not apply to sky
|
||||
if (fragmentDepth < 1.0)
|
||||
{
|
||||
vec3 viewPos = calcViewPosition(vec3(TexCoord, fragmentDepth));
|
||||
|
||||
// fading is done to prevent banding/noise
|
||||
// at super far distance
|
||||
float distanceFromCamera = length(viewPos);
|
||||
float fadeDistance = uFadeDistanceInBlocks;
|
||||
if (distanceFromCamera < fadeDistance)
|
||||
{
|
||||
#ifdef GL_ARB_derivative_control
|
||||
// Get higher precision derivatives when available
|
||||
vec3 viewNormal = cross(dFdxFine(viewPos.xyz), dFdyFine(viewPos.xyz));
|
||||
#else
|
||||
vec3 viewNormal = cross(dFdx(viewPos.xyz), dFdy(viewPos.xyz));
|
||||
#endif
|
||||
|
||||
viewNormal = normalize(viewNormal);
|
||||
occlusion = GetSpiralOcclusion(TexCoord, viewPos, viewNormal);
|
||||
|
||||
// linearly fade with distance
|
||||
occlusion *= (fadeDistance - distanceFromCamera) / fadeDistance;
|
||||
}
|
||||
else
|
||||
{
|
||||
// we're out of range, no need to do any SSAO calculations
|
||||
occlusion = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
fragColor = vec4(vec3(1.0 - occlusion), 1.0);
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
#version 150 core
|
||||
|
||||
in vec2 TexCoord;
|
||||
|
||||
out vec4 fragColor;
|
||||
|
||||
uniform sampler2D uSsaoColorTexture;
|
||||
uniform sampler2D uDhDepthTexture;
|
||||
|
||||
uniform vec2 gViewSize;
|
||||
uniform int gBlurRadius;
|
||||
uniform float gNear;
|
||||
uniform float gFar;
|
||||
|
||||
|
||||
float linearizeDepth(const in float depth) {
|
||||
return (gNear * gFar) / (depth * (gNear - gFar) + gFar);
|
||||
}
|
||||
|
||||
float Gaussian(const in float sigma, const in float x) {
|
||||
return exp(-(x*x) / (2.0 * (sigma*sigma)));
|
||||
}
|
||||
|
||||
float BilateralGaussianBlur(const in vec2 texcoord, const in float linearDepth, const in float g_sigmaV) {
|
||||
float g_sigmaX = 1.6;
|
||||
float g_sigmaY = 1.6;
|
||||
|
||||
int radius = clamp(gBlurRadius, 1, 3);
|
||||
|
||||
vec2 pixelSize = 1.0 / gViewSize;
|
||||
|
||||
float accum = 0.0;
|
||||
float total = 0.0;
|
||||
for (int iy = -radius; iy <= radius; iy++) {
|
||||
float fy = Gaussian(g_sigmaY, iy);
|
||||
|
||||
for (int ix = -radius; ix <= radius; ix++) {
|
||||
float fx = Gaussian(g_sigmaX, ix);
|
||||
|
||||
vec2 sampleTex = texcoord + ivec2(ix, iy) * pixelSize;
|
||||
float sampleValue = textureLod(uSsaoColorTexture, sampleTex, 0).r;
|
||||
float sampleDepth = textureLod(uDhDepthTexture, sampleTex, 0).r;
|
||||
float sampleLinearDepth = linearizeDepth(sampleDepth);
|
||||
|
||||
float depthDiff = abs(sampleLinearDepth - linearDepth);
|
||||
float fv = Gaussian(g_sigmaV, depthDiff);
|
||||
|
||||
float weight = fx*fy*fv;
|
||||
accum += weight * sampleValue;
|
||||
total += weight;
|
||||
}
|
||||
}
|
||||
|
||||
if (total <= 1.e-4) return 1.0;
|
||||
return accum / total;
|
||||
}
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
fragColor = vec4(1.0);
|
||||
|
||||
float fragmentDepth = textureLod(uDhDepthTexture, TexCoord, 0).r;
|
||||
|
||||
// a fragment depth of "1" means the fragment wasn't drawn to,
|
||||
// we only want to apply SSAO to LODs, not to the sky outside the LODs
|
||||
if (fragmentDepth < 1)
|
||||
{
|
||||
if (gBlurRadius > 0)
|
||||
{
|
||||
float fragmentDepthLinear = linearizeDepth(fragmentDepth);
|
||||
fragColor.a = BilateralGaussianBlur(TexCoord, fragmentDepthLinear, 1.6);
|
||||
}
|
||||
else
|
||||
{
|
||||
fragColor.a = texelFetch(uSsaoColorTexture, ivec2(gl_FragCoord.xy), 0).r;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
#version 150 core
|
||||
|
||||
in vec2 vPosition;
|
||||
|
||||
out vec2 TexCoord;
|
||||
|
||||
/**
|
||||
* This is specifically used by application shaders.
|
||||
* IE post process or pixel transfer shaders, anything that is rendered using a single rectangle.
|
||||
*/
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(vPosition, 1.0, 1.0);
|
||||
TexCoord = vPosition.xy * 0.5 + 0.5;
|
||||
}
|
||||
Reference in New Issue
Block a user