diff --git a/src/gl/renderer/gl_postprocess.cpp b/src/gl/renderer/gl_postprocess.cpp index 97e2c3be9..dd8bccc8b 100644 --- a/src/gl/renderer/gl_postprocess.cpp +++ b/src/gl/renderer/gl_postprocess.cpp @@ -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(); } diff --git a/src/gl/renderer/gl_renderbuffers.cpp b/src/gl/renderer/gl_renderbuffers.cpp index a24596562..b14ee9852 100644 --- a/src/gl/renderer/gl_renderbuffers.cpp +++ b/src/gl/renderer/gl_renderbuffers.cpp @@ -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); diff --git a/src/gl/renderer/gl_renderbuffers.h b/src/gl/renderer/gl_renderbuffers.h index d593b0248..efa61f3e2 100644 --- a/src/gl/renderer/gl_renderbuffers.h +++ b/src/gl/renderer/gl_renderbuffers.h @@ -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); diff --git a/src/gl/shaders/gl_ambientshader.cpp b/src/gl/shaders/gl_ambientshader.cpp index 0d08e1258..effde2496 100644 --- a/src/gl/shaders/gl_ambientshader.cpp +++ b/src/gl/shaders/gl_ambientshader.cpp @@ -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(); diff --git a/src/gl/shaders/gl_ambientshader.h b/src/gl/shaders/gl_ambientshader.h index 95dfd6bac..d3310c3d6 100644 --- a/src/gl/shaders/gl_ambientshader.h +++ b/src/gl/shaders/gl_ambientshader.h @@ -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 diff --git a/wadsrc/static/shaders/glsl/lineardepth.fp b/wadsrc/static/shaders/glsl/lineardepth.fp index fa71c9de0..3e2b3eb95 100644 --- a/wadsrc/static/shaders/glsl/lineardepth.fp +++ b/wadsrc/static/shaders/glsl/lineardepth.fp @@ -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); } diff --git a/wadsrc/static/shaders/glsl/ssao.fp b/wadsrc/static/shaders/glsl/ssao.fp index f895ddc25..3b2db6005 100644 --- a/wadsrc/static/shaders/glsl/ssao.fp +++ b/wadsrc/static/shaders/glsl/ssao.fp @@ -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); diff --git a/wadsrc/static/shaders/glsl/ssaocombine.fp b/wadsrc/static/shaders/glsl/ssaocombine.fp index 377516587..4ca64421b 100644 --- a/wadsrc/static/shaders/glsl/ssaocombine.fp +++ b/wadsrc/static/shaders/glsl/ssaocombine.fp @@ -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);