mirror of
https://github.com/ZDoom/qzdoom.git
synced 2025-01-18 15:11:46 +00:00
Multisampling ssao bug fixes and split linear depth to its own buffer
This commit is contained in:
parent
bb79dcb634
commit
1b7c42f45f
8 changed files with 55 additions and 48 deletions
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue