Change SSAO blur to be depth aware

This commit is contained in:
Magnus Norddahl 2016-09-02 05:45:00 +02:00
parent 5a0c61a2d5
commit 98032bc73f
9 changed files with 184 additions and 14 deletions

View file

@ -209,8 +209,22 @@ void FGLRenderer::AmbientOccludeScene()
RenderScreenQuad(); RenderScreenQuad();
// Blur SSAO texture // Blur SSAO texture
mBlurShader->BlurHorizontal(this, blurAmount, blurSampleCount, mBuffers->AmbientTexture1, mBuffers->AmbientFB0, mBuffers->AmbientWidth, mBuffers->AmbientHeight); glBindFramebuffer(GL_FRAMEBUFFER, mBuffers->AmbientFB0);
mBlurShader->BlurVertical(this, blurAmount, blurSampleCount, mBuffers->AmbientTexture0, mBuffers->AmbientFB1, mBuffers->AmbientWidth, mBuffers->AmbientHeight); glBindTexture(GL_TEXTURE_2D, mBuffers->AmbientTexture1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
mDepthBlurShader->Bind(false);
mDepthBlurShader->BlurSharpness[false].Set(blurAmount);
mDepthBlurShader->InvFullResolution[false].Set(1.0f / mBuffers->AmbientWidth, 1.0f / mBuffers->AmbientHeight);
RenderScreenQuad();
glBindFramebuffer(GL_FRAMEBUFFER, mBuffers->AmbientFB1);
glBindTexture(GL_TEXTURE_2D, mBuffers->AmbientTexture0);
mDepthBlurShader->Bind(true);
mDepthBlurShader->BlurSharpness[true].Set(blurAmount);
mDepthBlurShader->InvFullResolution[true].Set(1.0f / mBuffers->AmbientWidth, 1.0f / mBuffers->AmbientHeight);
mDepthBlurShader->PowExponent[true].Set(1.8f);
RenderScreenQuad();
// Add SSAO back to scene texture: // Add SSAO back to scene texture:
mBuffers->BindCurrentFB(); mBuffers->BindCurrentFB();
@ -225,8 +239,8 @@ void FGLRenderer::AmbientOccludeScene()
glBindTexture(GL_TEXTURE_2D, mBuffers->AmbientTexture1); glBindTexture(GL_TEXTURE_2D, mBuffers->AmbientTexture1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
mBloomCombineShader->Bind(); mSSAOCombineShader->Bind();
mBloomCombineShader->BloomTexture.Set(0); mSSAOCombineShader->AODepthTexture.Set(0);
RenderScreenQuad(); RenderScreenQuad();
glViewport(mScreenViewport.left, mScreenViewport.top, mScreenViewport.width, mScreenViewport.height); glViewport(mScreenViewport.left, mScreenViewport.top, mScreenViewport.width, mScreenViewport.height);

View file

@ -313,8 +313,8 @@ void FGLRenderBuffers::CreateAmbientOcclusion(int width, int height)
AmbientWidth = width / 2; AmbientWidth = width / 2;
AmbientHeight = height / 2; AmbientHeight = height / 2;
AmbientTexture0 = Create2DTexture("AmbientTexture0", GL_RGBA32F, AmbientWidth, AmbientHeight); AmbientTexture0 = Create2DTexture("AmbientTexture0", GL_RG32F, AmbientWidth, AmbientHeight);
AmbientTexture1 = Create2DTexture("AmbientTexture1", GL_RGBA32F, AmbientWidth, AmbientHeight); AmbientTexture1 = Create2DTexture("AmbientTexture1", GL_RG32F, AmbientWidth, AmbientHeight);
AmbientFB0 = CreateFrameBuffer("AmbientFB0", AmbientTexture0); AmbientFB0 = CreateFrameBuffer("AmbientFB0", AmbientTexture0);
AmbientFB1 = CreateFrameBuffer("AmbientFB1", AmbientTexture1); AmbientFB1 = CreateFrameBuffer("AmbientFB1", AmbientTexture1);
@ -370,6 +370,8 @@ GLuint FGLRenderBuffers::Create2DTexture(const FString &name, GLuint format, int
case GL_RGBA16: dataformat = GL_RGBA; datatype = GL_UNSIGNED_SHORT; break; case GL_RGBA16: dataformat = GL_RGBA; datatype = GL_UNSIGNED_SHORT; break;
case GL_RGBA16F: dataformat = GL_RGBA; datatype = GL_FLOAT; break; case GL_RGBA16F: dataformat = GL_RGBA; datatype = GL_FLOAT; break;
case GL_RGBA32F: dataformat = GL_RGBA; datatype = GL_FLOAT; break; case GL_RGBA32F: dataformat = GL_RGBA; datatype = GL_FLOAT; break;
case GL_R32F: dataformat = GL_RED; datatype = GL_FLOAT; break;
case GL_RG32F: dataformat = GL_RG; datatype = GL_FLOAT; break;
case GL_DEPTH_COMPONENT24: dataformat = GL_DEPTH_COMPONENT; datatype = GL_FLOAT; break; case GL_DEPTH_COMPONENT24: dataformat = GL_DEPTH_COMPONENT; datatype = GL_FLOAT; break;
case GL_STENCIL_INDEX8: dataformat = GL_STENCIL_INDEX; datatype = GL_INT; break; case GL_STENCIL_INDEX8: dataformat = GL_STENCIL_INDEX; datatype = GL_INT; break;
case GL_DEPTH24_STENCIL8: dataformat = GL_DEPTH_STENCIL; datatype = GL_UNSIGNED_INT_24_8; break; case GL_DEPTH24_STENCIL8: dataformat = GL_DEPTH_STENCIL; datatype = GL_UNSIGNED_INT_24_8; break;

View file

@ -123,6 +123,10 @@ FGLRenderer::FGLRenderer(OpenGLFrameBuffer *fb)
mTonemapPalette = nullptr; mTonemapPalette = nullptr;
mColormapShader = nullptr; mColormapShader = nullptr;
mLensShader = nullptr; mLensShader = nullptr;
mLinearDepthShader = nullptr;
mDepthBlurShader = nullptr;
mSSAOShader = nullptr;
mSSAOCombineShader = nullptr;
} }
void gl_LoadModels(); void gl_LoadModels();
@ -132,7 +136,9 @@ void FGLRenderer::Initialize(int width, int height)
{ {
mBuffers = new FGLRenderBuffers(); mBuffers = new FGLRenderBuffers();
mLinearDepthShader = new FLinearDepthShader(); mLinearDepthShader = new FLinearDepthShader();
mDepthBlurShader = new FDepthBlurShader();
mSSAOShader = new FSSAOShader(); mSSAOShader = new FSSAOShader();
mSSAOCombineShader = new FSSAOCombineShader();
mBloomExtractShader = new FBloomExtractShader(); mBloomExtractShader = new FBloomExtractShader();
mBloomCombineShader = new FBloomCombineShader(); mBloomCombineShader = new FBloomCombineShader();
mBlurShader = new FBlurShader(); mBlurShader = new FBlurShader();
@ -194,7 +200,9 @@ FGLRenderer::~FGLRenderer()
if (mBuffers) delete mBuffers; if (mBuffers) delete mBuffers;
if (mPresentShader) delete mPresentShader; if (mPresentShader) delete mPresentShader;
if (mLinearDepthShader) delete mLinearDepthShader; if (mLinearDepthShader) delete mLinearDepthShader;
if (mDepthBlurShader) delete mDepthBlurShader;
if (mSSAOShader) delete mSSAOShader; if (mSSAOShader) delete mSSAOShader;
if (mSSAOCombineShader) delete mSSAOCombineShader;
if (mBloomExtractShader) delete mBloomExtractShader; if (mBloomExtractShader) delete mBloomExtractShader;
if (mBloomCombineShader) delete mBloomCombineShader; if (mBloomCombineShader) delete mBloomCombineShader;
if (mBlurShader) delete mBlurShader; if (mBlurShader) delete mBlurShader;

View file

@ -20,7 +20,9 @@ class FSamplerManager;
class DPSprite; class DPSprite;
class FGLRenderBuffers; class FGLRenderBuffers;
class FLinearDepthShader; class FLinearDepthShader;
class FDepthBlurShader;
class FSSAOShader; class FSSAOShader;
class FSSAOCombineShader;
class FBloomExtractShader; class FBloomExtractShader;
class FBloomCombineShader; class FBloomCombineShader;
class FBlurShader; class FBlurShader;
@ -94,6 +96,8 @@ public:
FGLRenderBuffers *mBuffers; FGLRenderBuffers *mBuffers;
FLinearDepthShader *mLinearDepthShader; FLinearDepthShader *mLinearDepthShader;
FSSAOShader *mSSAOShader; FSSAOShader *mSSAOShader;
FDepthBlurShader *mDepthBlurShader;
FSSAOCombineShader *mSSAOCombineShader;
FBloomExtractShader *mBloomExtractShader; FBloomExtractShader *mBloomExtractShader;
FBloomCombineShader *mBloomCombineShader; FBloomCombineShader *mBloomCombineShader;
FBlurShader *mBlurShader; FBlurShader *mBlurShader;

View file

@ -96,3 +96,35 @@ void FSSAOShader::Bind()
} }
mShader.Bind(); mShader.Bind();
} }
void FDepthBlurShader::Bind(bool vertical)
{
auto &shader = mShader[vertical];
if (!shader)
{
shader.Compile(FShaderProgram::Vertex, "shaders/glsl/screenquad.vp", "", 330);
shader.Compile(FShaderProgram::Fragment, "shaders/glsl/depthblur.fp", vertical ? "#define BLUR_VERTICAL\n" : "#define BLUR_HORIZONTAL\n", 330);
shader.SetFragDataLocation(0, "FragColor");
shader.Link("shaders/glsl/depthblur");
shader.SetAttribLocation(0, "PositionInProjection");
AODepthTexture[vertical].Init(shader, "AODepthTexture");
BlurSharpness[vertical].Init(shader, "BlurSharpness");
InvFullResolution[vertical].Init(shader, "InvFullResolution");
PowExponent[vertical].Init(shader, "PowExponent");
}
shader.Bind();
}
void FSSAOCombineShader::Bind()
{
if (!mShader)
{
mShader.Compile(FShaderProgram::Vertex, "shaders/glsl/screenquad.vp", "", 330);
mShader.Compile(FShaderProgram::Fragment, "shaders/glsl/ssaocombine.fp", "", 330);
mShader.SetFragDataLocation(0, "FragColor");
mShader.Link("shaders/glsl/ssaocombine");
mShader.SetAttribLocation(0, "PositionInProjection");
AODepthTexture.Init(mShader, "AODepthTexture");
}
mShader.Bind();
}

View file

@ -38,4 +38,29 @@ private:
FShaderProgram mShader; FShaderProgram mShader;
}; };
class FDepthBlurShader
{
public:
void Bind(bool vertical);
FBufferedUniformSampler AODepthTexture[2];
FBufferedUniform1f BlurSharpness[2];
FBufferedUniform2f InvFullResolution[2];
FBufferedUniform1f PowExponent[2];
private:
FShaderProgram mShader[2];
};
class FSSAOCombineShader
{
public:
void Bind();
FBufferedUniformSampler AODepthTexture;
private:
FShaderProgram mShader;
};
#endif #endif

View file

@ -0,0 +1,81 @@
in vec2 TexCoord;
out vec4 FragColor;
uniform sampler2D AODepthTexture;
uniform float BlurSharpness;
uniform vec2 InvFullResolution;
uniform float PowExponent;
#define KERNEL_RADIUS 3.0
struct CenterPixelData
{
vec2 UV;
float Depth;
float Sharpness;
};
float CrossBilateralWeight(float r, float sampleDepth, CenterPixelData center)
{
const float blurSigma = KERNEL_RADIUS * 0.5;
const float blurFalloff = 1.0 / (2.0 * blurSigma * blurSigma);
float deltaZ = (sampleDepth - center.Depth) * center.Sharpness;
return exp2(-r * r * blurFalloff - deltaZ * deltaZ);
}
void ProcessSample(float ao, float z, float r, CenterPixelData center, inout float totalAO, inout float totalW)
{
float w = CrossBilateralWeight(r, z, center);
totalAO += w * ao;
totalW += w;
}
void ProcessRadius(vec2 deltaUV, CenterPixelData center, inout float totalAO, inout float totalW)
{
for (float r = 1; r <= KERNEL_RADIUS; r += 1.0)
{
vec2 uv = r * deltaUV + center.UV;
vec2 aoZ = texture(AODepthTexture, uv).xy;
ProcessSample(aoZ.x, aoZ.y, r, center, totalAO, totalW);
}
}
vec2 ComputeBlur(vec2 deltaUV)
{
vec2 aoZ = texture(AODepthTexture, TexCoord).xy;
CenterPixelData center;
center.UV = TexCoord;
center.Depth = aoZ.y;
center.Sharpness = BlurSharpness;
float totalAO = aoZ.x;
float totalW = 1.0;
ProcessRadius(deltaUV, center, totalAO, totalW);
ProcessRadius(-deltaUV, center, totalAO, totalW);
return vec2(totalAO / totalW, aoZ.y);
}
vec2 BlurX()
{
return ComputeBlur(vec2(InvFullResolution.x, 0.0));
}
float BlurY()
{
return pow(clamp(ComputeBlur(vec2(0.0, InvFullResolution.y)).x, 0.0, 1.0), PowExponent);
}
void main()
{
#if defined(BLUR_HORIZONTAL)
FragColor = vec4(BlurX(), 0.0, 1.0);
#else
FragColor = vec4(BlurY(), 0.0, 0.0, 1.0);
#endif
}

View file

@ -108,12 +108,5 @@ void main()
vec3 viewPosition = FetchViewPos(TexCoord); vec3 viewPosition = FetchViewPos(TexCoord);
vec3 viewNormal = ReconstructNormal(viewPosition); vec3 viewNormal = ReconstructNormal(viewPosition);
float occlusion = ComputeAO(viewPosition, viewNormal) * AOStrength + (1.0 - AOStrength); float occlusion = ComputeAO(viewPosition, viewNormal) * AOStrength + (1.0 - AOStrength);
FragColor = vec4(occlusion, viewPosition.z, 0.0, 1.0);
// GZDoom does not use linear buffers at the moment, apply some gamma to get it closer to correct
occlusion = occlusion * occlusion;
//FragColor = vec4(viewPosition.x * 0.001 + 0.5, viewPosition.y * 0.001 + 0.5, viewPosition.z * 0.001, 1.0);
//FragColor = vec4(viewNormal.x * 0.5 + 0.5, viewNormal.y * 0.5 + 0.5, viewNormal.z * 0.5 + 0.5, 1.0);
//FragColor = vec4(occlusion, viewPosition.z, 0.0, 1.0);
FragColor = vec4(occlusion, occlusion, occlusion, 1.0);
} }

View file

@ -0,0 +1,11 @@
in vec2 TexCoord;
out vec4 FragColor;
uniform sampler2D AODepthTexture;
void main()
{
float attenutation = texture(AODepthTexture, TexCoord).x;
FragColor = vec4(attenutation, attenutation, attenutation, 0.0);
}