Multisampling ssao bug fixes and split linear depth to its own buffer

This commit is contained in:
Magnus Norddahl 2016-10-09 06:17:48 +02:00
parent bb79dcb634
commit 1b7c42f45f
8 changed files with 55 additions and 48 deletions

View file

@ -122,9 +122,14 @@ CUSTOM_CVAR(Int, gl_ssao_portals, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
CVAR(Float, gl_ssao_strength, 0.7, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
CVAR(Int, gl_ssao_debug, 0, 0)
CVAR(Float, gl_ssao_bias, 0.5f, 0)
CVAR(Float, gl_ssao_radius, 100.0f, 0)
CUSTOM_CVAR(Float, gl_ssao_blur_amount, 16.0f, 0)
CVAR(Float, gl_ssao_bias, 0.2f, 0)
CVAR(Float, gl_ssao_radius, 80.0f, 0)
CUSTOM_CVAR(Float, gl_ssao_blur, 16.0f, 0)
{
if (self < 0.1f) self = 0.1f;
}
CUSTOM_CVAR(Float, gl_ssao_exponent, 1.8f, 0)
{
if (self < 0.1f) self = 0.1f;
}
@ -166,7 +171,7 @@ void FGLRenderer::AmbientOccludeScene()
float bias = gl_ssao_bias;
float aoRadius = gl_ssao_radius;
const float blurAmount = gl_ssao_blur_amount;
const float blurAmount = gl_ssao_blur;
float aoStrength = gl_ssao_strength;
//float tanHalfFovy = tan(fovy * (M_PI / 360.0f));
@ -186,7 +191,7 @@ void FGLRenderer::AmbientOccludeScene()
int randomTexture = clamp(gl_ssao - 1, 0, FGLRenderBuffers::NumAmbientRandomTextures - 1);
// Calculate linear depth values
glBindFramebuffer(GL_FRAMEBUFFER, mBuffers->AmbientFB0);
glBindFramebuffer(GL_FRAMEBUFFER, mBuffers->LinearDepthFB);
glViewport(0, 0, mBuffers->AmbientWidth, mBuffers->AmbientHeight);
mBuffers->BindSceneDepthTexture(0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
@ -198,7 +203,7 @@ void FGLRenderer::AmbientOccludeScene()
mLinearDepthShader->Bind();
mLinearDepthShader->DepthTexture.Set(0);
mLinearDepthShader->ColorTexture.Set(1);
if (gl_multisample > 1) mLinearDepthShader->SampleCount.Set(gl_multisample);
if (gl_multisample > 1) mLinearDepthShader->SampleIndex.Set(0);
mLinearDepthShader->LinearizeDepthA.Set(1.0f / GetZFar() - 1.0f / GetZNear());
mLinearDepthShader->LinearizeDepthB.Set(MAX(1.0f / GetZNear(), 1.e-8f));
mLinearDepthShader->InverseDepthRangeA.Set(1.0f);
@ -209,7 +214,7 @@ void FGLRenderer::AmbientOccludeScene()
// Apply ambient occlusion
glBindFramebuffer(GL_FRAMEBUFFER, mBuffers->AmbientFB1);
glBindTexture(GL_TEXTURE_2D, mBuffers->AmbientTexture0);
glBindTexture(GL_TEXTURE_2D, mBuffers->LinearDepthTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glActiveTexture(GL_TEXTURE1);
@ -226,6 +231,7 @@ void FGLRenderer::AmbientOccludeScene()
mSSAOShader->DepthTexture.Set(0);
mSSAOShader->RandomTexture.Set(1);
mSSAOShader->NormalTexture.Set(2);
if (gl_multisample > 1) mSSAOShader->SampleIndex.Set(0);
mSSAOShader->UVToViewA.Set(2.0f * invFocalLenX, 2.0f * invFocalLenY);
mSSAOShader->UVToViewB.Set(-invFocalLenX, -invFocalLenY);
mSSAOShader->InvFullResolution.Set(1.0f / mBuffers->AmbientWidth, 1.0f / mBuffers->AmbientHeight);
@ -255,7 +261,7 @@ void FGLRenderer::AmbientOccludeScene()
mDepthBlurShader->Bind(true);
mDepthBlurShader->BlurSharpness[true].Set(blurSharpness);
mDepthBlurShader->InvFullResolution[true].Set(1.0f / mBuffers->AmbientWidth, 1.0f / mBuffers->AmbientHeight);
mDepthBlurShader->PowExponent[true].Set(1.8f);
mDepthBlurShader->PowExponent[true].Set(gl_ssao_exponent);
RenderScreenQuad();
}

View file

@ -152,8 +152,10 @@ void FGLRenderBuffers::ClearEyeBuffers()
void FGLRenderBuffers::ClearAmbientOcclusion()
{
DeleteFrameBuffer(LinearDepthFB);
DeleteFrameBuffer(AmbientFB0);
DeleteFrameBuffer(AmbientFB1);
DeleteTexture(LinearDepthTexture);
DeleteTexture(AmbientTexture0);
DeleteTexture(AmbientTexture1);
for (int i = 0; i < NumAmbientRandomTextures; i++)
@ -336,13 +338,13 @@ void FGLRenderBuffers::CreateBloom(int width, int height)
if (width <= 0 || height <= 0)
return;
int bloomWidth = MAX(width / 2, 1);
int bloomHeight = MAX(height / 2, 1);
int bloomWidth = (width + 1) / 2;
int bloomHeight = (height + 1) / 2;
for (int i = 0; i < NumBloomLevels; i++)
{
auto &level = BloomLevels[i];
level.Width = MAX(bloomWidth / 2, 1);
level.Height = MAX(bloomHeight / 2, 1);
level.Width = (bloomWidth + 1) / 2;
level.Height = (bloomHeight + 1) / 2;
level.VTexture = Create2DTexture("Bloom.VTexture", GL_RGBA16F, level.Width, level.Height);
level.HTexture = Create2DTexture("Bloom.HTexture", GL_RGBA16F, level.Width, level.Height);
@ -367,10 +369,12 @@ void FGLRenderBuffers::CreateAmbientOcclusion(int width, int height)
if (width <= 0 || height <= 0)
return;
AmbientWidth = width / 2;
AmbientHeight = height / 2;
AmbientTexture0 = Create2DTexture("AmbientTexture0", GL_RG32F, AmbientWidth, AmbientHeight);
AmbientTexture1 = Create2DTexture("AmbientTexture1", GL_RG32F, AmbientWidth, AmbientHeight);
AmbientWidth = (width + 1) / 2;
AmbientHeight = (height + 1) / 2;
LinearDepthTexture = Create2DTexture("LinearDepthTexture", GL_R32F, AmbientWidth, AmbientHeight);
AmbientTexture0 = Create2DTexture("AmbientTexture0", GL_RG16F, AmbientWidth, AmbientHeight);
AmbientTexture1 = Create2DTexture("AmbientTexture1", GL_RG16F, AmbientWidth, AmbientHeight);
LinearDepthFB = CreateFrameBuffer("LinearDepthFB", LinearDepthTexture);
AmbientFB0 = CreateFrameBuffer("AmbientFB0", AmbientTexture0);
AmbientFB1 = CreateFrameBuffer("AmbientFB1", AmbientTexture1);
@ -485,13 +489,15 @@ GLuint FGLRenderBuffers::Create2DTexture(const FString &name, GLuint format, int
case GL_RGBA16: dataformat = GL_RGBA; datatype = GL_UNSIGNED_SHORT; break;
case GL_RGBA16F: dataformat = GL_RGBA; datatype = GL_FLOAT; break;
case GL_RGBA32F: dataformat = GL_RGBA; datatype = GL_FLOAT; break;
case GL_RGBA16_SNORM: dataformat = GL_RGBA; datatype = GL_SHORT; break;
case GL_R32F: dataformat = GL_RED; datatype = GL_FLOAT; break;
case GL_R16F: dataformat = GL_RED; datatype = GL_FLOAT; break;
case GL_RG32F: dataformat = GL_RG; datatype = GL_FLOAT; break;
case GL_RG16F: dataformat = GL_RG; datatype = GL_FLOAT; break;
case GL_RGB10_A2: dataformat = GL_RGBA; datatype = GL_UNSIGNED_INT_10_10_10_2; 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_DEPTH24_STENCIL8: dataformat = GL_DEPTH_STENCIL; datatype = GL_UNSIGNED_INT_24_8; break;
case GL_RGBA16_SNORM: dataformat = GL_RGBA; datatype = GL_SHORT; break;
default: I_FatalError("Unknown format passed to FGLRenderBuffers.Create2DTexture");
}
@ -530,7 +536,7 @@ GLuint FGLRenderBuffers::CreateRenderBuffer(const FString &name, GLuint format,
return handle;
}
GLuint FGLRenderBuffers::CreateRenderBuffer(const FString &name, GLuint format, int samples, int width, int height)
GLuint FGLRenderBuffers::CreateRenderBuffer(const FString &name, GLuint format, int width, int height, int samples)
{
if (samples <= 1)
return CreateRenderBuffer(name, format, width, height);

View file

@ -59,6 +59,8 @@ public:
bool FirstExposureFrame = true;
// Ambient occlusion buffers
GLuint LinearDepthTexture = 0;
GLuint LinearDepthFB = 0;
GLuint AmbientTexture0 = 0;
GLuint AmbientTexture1 = 0;
GLuint AmbientFB0 = 0;
@ -92,7 +94,7 @@ private:
GLuint Create2DTexture(const FString &name, GLuint format, int width, int height, const void *data = nullptr);
GLuint Create2DMultisampleTexture(const FString &name, GLuint format, int width, int height, int samples, bool fixedSampleLocations);
GLuint CreateRenderBuffer(const FString &name, GLuint format, int width, int height);
GLuint CreateRenderBuffer(const FString &name, GLuint format, int samples, int width, int height);
GLuint CreateRenderBuffer(const FString &name, GLuint format, int width, int height, int samples);
GLuint CreateFrameBuffer(const FString &name, GLuint colorbuffer);
GLuint CreateFrameBuffer(const FString &name, GLuint colorbuffer, GLuint depthstencil, bool colorIsARenderBuffer);
GLuint CreateFrameBuffer(const FString &name, GLuint colorbuffer0, GLuint colorbuffer1, GLuint colorbuffer2, GLuint depthstencil, bool multisample);

View file

@ -47,7 +47,7 @@ void FLinearDepthShader::Bind()
mShader->SetAttribLocation(0, "PositionInProjection");
DepthTexture.Init(*mShader, "DepthTexture");
ColorTexture.Init(*mShader, "ColorTexture");
SampleCount.Init(*mShader, "SampleCount");
SampleIndex.Init(*mShader, "SampleIndex");
LinearizeDepthA.Init(*mShader, "LinearizeDepthA");
LinearizeDepthB.Init(*mShader, "LinearizeDepthB");
InverseDepthRangeA.Init(*mShader, "InverseDepthRangeA");
@ -86,6 +86,7 @@ void FSSAOShader::Bind()
AOStrength.Init(*mShader, "AOStrength");
Scale.Init(*mShader, "Scale");
Offset.Init(*mShader, "Offset");
SampleIndex.Init(*mShader, "SampleIndex");
mMultisample = multisample;
}
mShader->Bind();

View file

@ -10,7 +10,7 @@ public:
FBufferedUniformSampler DepthTexture;
FBufferedUniformSampler ColorTexture;
FBufferedUniform1i SampleCount;
FBufferedUniform1i SampleIndex;
FBufferedUniform1f LinearizeDepthA;
FBufferedUniform1f LinearizeDepthB;
FBufferedUniform1f InverseDepthRangeA;
@ -41,6 +41,7 @@ public:
FBufferedUniform1f AOStrength;
FBufferedUniform2f Scale;
FBufferedUniform2f Offset;
FBufferedUniform1i SampleIndex;
private:
enum Quality

View file

@ -5,7 +5,7 @@ out vec4 FragColor;
#if defined(MULTISAMPLE)
uniform sampler2DMS DepthTexture;
uniform sampler2DMS ColorTexture;
uniform int SampleCount;
uniform int SampleIndex;
#else
uniform sampler2D DepthTexture;
uniform sampler2D ColorTexture;
@ -37,21 +37,10 @@ void main()
ivec2 ipos = ivec2(max(uv * vec2(texSize), vec2(0.0)));
#if defined(MULTISAMPLE)
float depth = normalizeDepth(texelFetch(ColorTexture, ipos, 0).a != 0.0 ? texelFetch(DepthTexture, ipos, 0).x : 1.0);
float sampleIndex = 0.0;
for (int i = 1; i < SampleCount; i++)
{
float hardwareDepth = texelFetch(ColorTexture, ipos, i).a != 0.0 ? texelFetch(DepthTexture, ipos, i).x : 1.0;
float sampleDepth = normalizeDepth(hardwareDepth);
if (sampleDepth < depth)
{
depth = sampleDepth;
sampleIndex = float(i);
}
}
FragColor = vec4(depth, sampleIndex, 0.0, 1.0);
float depth = normalizeDepth(texelFetch(ColorTexture, ipos, SampleIndex).a != 0.0 ? texelFetch(DepthTexture, ipos, SampleIndex).x : 1.0);
#else
float depth = normalizeDepth(texelFetch(ColorTexture, ipos, 0).a != 0.0 ? texelFetch(DepthTexture, ipos, 0).x : 1.0);
FragColor = vec4(depth, 0.0, 0.0, 1.0);
#endif
FragColor = vec4(depth, 0.0, 0.0, 1.0);
}

View file

@ -20,6 +20,7 @@ uniform sampler2D DepthTexture;
#if defined(MULTISAMPLE)
uniform sampler2DMS NormalTexture;
uniform int SampleIndex;
#else
uniform sampler2D NormalTexture;
#endif
@ -30,21 +31,22 @@ uniform sampler2D RandomTexture;
#define PI 3.14159265358979323846
// Calculate eye space position for the specified texture coordinate and depth
vec3 FetchViewPos(vec2 uv, float z)
// Calculate eye space position for the specified texture coordinate
vec3 FetchViewPos(vec2 uv)
{
float z = texture(DepthTexture, uv).x;
return vec3((UVToViewA * uv + UVToViewB) * z, z);
}
#if defined(MULTISAMPLE)
vec3 SampleNormal(vec2 uv, float samplerIndex)
vec3 SampleNormal(vec2 uv)
{
ivec2 texSize = textureSize(NormalTexture);
ivec2 ipos = ivec2(uv * vec2(texSize));
return texelFetch(NormalTexture, ipos, int(samplerIndex)).xyz * 2.0 - 1.0;
return texelFetch(NormalTexture, ipos, SampleIndex).xyz * 2.0 - 1.0;
}
#else
vec3 SampleNormal(vec2 uv, float samplerIndex)
vec3 SampleNormal(vec2 uv)
{
ivec2 texSize = textureSize(NormalTexture, 0);
ivec2 ipos = ivec2(uv * vec2(texSize));
@ -53,9 +55,9 @@ vec3 SampleNormal(vec2 uv, float samplerIndex)
#endif
// Look up the eye space normal for the specified texture coordinate
vec3 FetchNormal(vec2 uv, float samplerIndex)
vec3 FetchNormal(vec2 uv)
{
vec3 normal = SampleNormal(Offset + uv * Scale, samplerIndex);
vec3 normal = SampleNormal(Offset + uv * Scale);
if (length(normal) > 0.1)
{
normal = normalize(normal);
@ -116,7 +118,7 @@ float ComputeAO(vec3 viewPosition, vec3 viewNormal)
for (float StepIndex = 0.0; StepIndex < NUM_STEPS; ++StepIndex)
{
vec2 sampleUV = round(rayPixels * direction) * InvFullResolution + TexCoord;
vec3 samplePos = FetchViewPos(sampleUV, texture(DepthTexture, sampleUV).x);
vec3 samplePos = FetchViewPos(sampleUV);
ao += ComputeSampleAO(viewPosition, viewNormal, samplePos);
rayPixels += stepSizePixels;
}
@ -128,9 +130,8 @@ float ComputeAO(vec3 viewPosition, vec3 viewNormal)
void main()
{
vec2 depthData = texture(DepthTexture, TexCoord).xy;
vec3 viewPosition = FetchViewPos(TexCoord, depthData.x);
vec3 viewNormal = FetchNormal(TexCoord, depthData.y);
vec3 viewPosition = FetchViewPos(TexCoord);
vec3 viewNormal = FetchNormal(TexCoord);
float occlusion = viewNormal != vec3(0.0) ? ComputeAO(viewPosition, viewNormal) * AOStrength + (1.0 - AOStrength) : 1.0;
FragColor = vec4(occlusion, viewPosition.z, 0.0, 1.0);

View file

@ -17,12 +17,13 @@ uniform vec2 Offset;
void main()
{
vec2 uv = Offset + TexCoord * Scale;
#if defined(MULTISAMPLE)
ivec2 texSize = textureSize(SceneFogTexture);
#else
ivec2 texSize = textureSize(SceneFogTexture, 0);
#endif
ivec2 ipos = ivec2(max(floor(uv * vec2(texSize) - 0.75), vec2(0.0)));
ivec2 ipos = ivec2(uv * vec2(texSize));
#if defined(MULTISAMPLE)
vec3 fogColor = vec3(0.0);