From 902097d6da05cc4e4ca315d40bccef7dcf791d8a Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sat, 3 Sep 2016 04:12:00 +0200 Subject: [PATCH] Resolve multisampling depth in shader --- src/gl/renderer/gl_postprocess.cpp | 20 ++- src/gl/renderer/gl_renderbuffers.cpp | 186 ++++++++++++++++------ src/gl/renderer/gl_renderbuffers.h | 27 +++- src/gl/shaders/gl_ambientshader.cpp | 28 ++-- src/gl/shaders/gl_ambientshader.h | 15 +- wadsrc/static/shaders/glsl/lineardepth.fp | 19 +++ 6 files changed, 211 insertions(+), 84 deletions(-) diff --git a/src/gl/renderer/gl_postprocess.cpp b/src/gl/renderer/gl_postprocess.cpp index edf1148ef7..1cd893f1ce 100644 --- a/src/gl/renderer/gl_postprocess.cpp +++ b/src/gl/renderer/gl_postprocess.cpp @@ -136,8 +136,8 @@ void FGLRenderer::RenderScreenQuad() void FGLRenderer::PostProcessScene() { - mBuffers->BlitSceneToTexture(); AmbientOccludeScene(); + mBuffers->BlitSceneToTexture(); BloomScene(); TonemapScene(); ColormapScene(); @@ -165,6 +165,7 @@ void FGLRenderer::AmbientOccludeScene() const float blurAmount = gl_ssao_blur_amount; int blurSampleCount = gl_ssao_blur_samples; float aoStrength = gl_ssao_strength; + bool multisample = gl_multisample > 1; //float tanHalfFovy = tan(fovy * (M_PI / 360.0f)); float tanHalfFovy = 1.0f / 1.33333302f; // 1.0f / gl_RenderState.mProjectionMatrix.get()[5]; @@ -177,12 +178,15 @@ void FGLRenderer::AmbientOccludeScene() glBindFramebuffer(GL_FRAMEBUFFER, mBuffers->AmbientFB0); glViewport(0, 0, mBuffers->AmbientWidth, mBuffers->AmbientHeight); mBuffers->BindSceneDepthTexture(0); - mLinearDepthShader->Bind(); - mLinearDepthShader->DepthTexture.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); - mLinearDepthShader->InverseDepthRangeB.Set(0.0f); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + mLinearDepthShader->Bind(multisample); + mLinearDepthShader->DepthTexture[multisample].Set(0); + if (multisample) mLinearDepthShader->SampleCount[multisample].Set(gl_multisample); + mLinearDepthShader->LinearizeDepthA[multisample].Set(1.0f / GetZFar() - 1.0f / GetZNear()); + mLinearDepthShader->LinearizeDepthB[multisample].Set(MAX(1.0f / GetZNear(), 1.e-8f)); + mLinearDepthShader->InverseDepthRangeA[multisample].Set(1.0f); + mLinearDepthShader->InverseDepthRangeB[multisample].Set(0.0f); RenderScreenQuad(); // Apply ambient occlusion @@ -227,7 +231,7 @@ void FGLRenderer::AmbientOccludeScene() RenderScreenQuad(); // Add SSAO back to scene texture: - mBuffers->BindCurrentFB(); + mBuffers->BindSceneFB(); glViewport(mSceneViewport.left, mSceneViewport.top, mSceneViewport.width, mSceneViewport.height); glEnable(GL_BLEND); glBlendEquation(GL_FUNC_ADD); diff --git a/src/gl/renderer/gl_renderbuffers.cpp b/src/gl/renderer/gl_renderbuffers.cpp index f66ea1354e..b2cee57049 100644 --- a/src/gl/renderer/gl_renderbuffers.cpp +++ b/src/gl/renderer/gl_renderbuffers.cpp @@ -53,6 +53,7 @@ #include "w_wad.h" #include "i_system.h" #include "doomerrors.h" +#include CVAR(Int, gl_multisample, 1, CVAR_ARCHIVE|CVAR_GLOBALCONFIG); CVAR(Bool, gl_renderbuffers, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL) @@ -86,15 +87,14 @@ FGLRenderBuffers::~FGLRenderBuffers() ClearScene(); ClearPipeline(); ClearBloom(); + ClearAmbientOcclusion(); } void FGLRenderBuffers::ClearScene() { DeleteFrameBuffer(mSceneFB); - DeleteRenderBuffer(mSceneMultisample); - DeleteRenderBuffer(mSceneDepthStencil); - DeleteRenderBuffer(mSceneDepth); - DeleteRenderBuffer(mSceneStencil); + DeleteTexture(mSceneMultisample); + DeleteTexture(mSceneDepthStencil); } void FGLRenderBuffers::ClearPipeline() @@ -119,6 +119,15 @@ void FGLRenderBuffers::ClearBloom() } } +void FGLRenderBuffers::ClearAmbientOcclusion() +{ + DeleteFrameBuffer(AmbientFB0); + DeleteFrameBuffer(AmbientFB1); + DeleteTexture(AmbientTexture0); + DeleteTexture(AmbientTexture1); + DeleteTexture(AmbientRandomTexture); +} + void FGLRenderBuffers::DeleteTexture(GLuint &handle) { if (handle != 0) @@ -186,11 +195,12 @@ bool FGLRenderBuffers::Setup(int width, int height, int sceneWidth, int sceneHei } // Bloom bluring buffers need to match the scene to avoid bloom bleeding artifacts - if (mBloomWidth != sceneWidth || mBloomHeight != sceneHeight) + if (mSceneWidth != sceneWidth || mSceneHeight != sceneHeight) { CreateBloom(sceneWidth, sceneHeight); - mBloomWidth = sceneWidth; - mBloomHeight = sceneHeight; + CreateAmbientOcclusion(sceneWidth, sceneHeight); + mSceneWidth = sceneWidth; + mSceneHeight = sceneHeight; } glBindTexture(GL_TEXTURE_2D, textureBinding); @@ -206,8 +216,8 @@ bool FGLRenderBuffers::Setup(int width, int height, int sceneWidth, int sceneHei mWidth = 0; mHeight = 0; mSamples = 0; - mBloomWidth = 0; - mBloomHeight = 0; + mSceneWidth = 0; + mSceneHeight = 0; } return !FailedCreate; @@ -224,9 +234,15 @@ void FGLRenderBuffers::CreateScene(int width, int height, int samples) ClearScene(); if (samples > 1) - mSceneMultisample = CreateRenderBuffer("SceneMultisample", GL_RGBA16F, samples, width, height); + { + mSceneMultisample = Create2DMultisampleTexture("SceneMultisample", GL_RGBA16F, width, height, samples, false); + mSceneDepthStencil = Create2DMultisampleTexture("SceneDepthStencil", GL_DEPTH24_STENCIL8, width, height, samples, false); + } + else + { + mSceneDepthStencil = Create2DTexture("SceneDepthStencil", GL_DEPTH24_STENCIL8, width, height); + } - mSceneDepthStencil = CreateRenderBuffer("SceneDepthStencil", GL_DEPTH24_STENCIL8, samples, width, height); mSceneFB = CreateFrameBuffer("SceneFB", samples > 1 ? mSceneMultisample : mPipelineTexture[0], mSceneDepthStencil, samples > 1); } @@ -279,20 +295,77 @@ void FGLRenderBuffers::CreateBloom(int width, int height) } } +//========================================================================== +// +// Creates ambient occlusion working buffers +// +//========================================================================== + +void FGLRenderBuffers::CreateAmbientOcclusion(int width, int height) +{ + ClearAmbientOcclusion(); + + 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); + AmbientFB0 = CreateFrameBuffer("AmbientFB0", AmbientTexture0); + AmbientFB1 = CreateFrameBuffer("AmbientFB1", AmbientTexture1); + + int16_t randomValues[16 * 4]; + std::mt19937 generator(1337); + std::uniform_real_distribution distribution(-1.0, 1.0); + for (int i = 0; i < 16; i++) + { + double num_directions = 8.0; // Must be same as the define in ssao.fp + double angle = 2.0 * M_PI * distribution(generator) / num_directions; + double x = cos(angle); + double y = sin(angle); + double z = distribution(generator); + double w = distribution(generator); + + randomValues[i * 4 + 0] = (int16_t)clamp(x * 32768.0, -32767.0, 32768.0); + randomValues[i * 4 + 1] = (int16_t)clamp(y * 32768.0, -32767.0, 32768.0); + randomValues[i * 4 + 2] = (int16_t)clamp(z * 32768.0, -32767.0, 32768.0); + randomValues[i * 4 + 3] = (int16_t)clamp(w * 32768.0, -32767.0, 32768.0); + } + + AmbientRandomTexture = Create2DTexture("AmbientRandomTexture", GL_RGBA16_SNORM, 4, 4, randomValues); +} + //========================================================================== // // Creates a 2D texture defaulting to linear filtering and clamp to edge // //========================================================================== -GLuint FGLRenderBuffers::Create2DTexture(const FString &name, GLuint format, int width, int height) +GLuint FGLRenderBuffers::Create2DTexture(const FString &name, GLuint format, int width, int height, const void *data) { - GLuint type = (format == GL_RGBA16F) ? GL_FLOAT : GL_UNSIGNED_BYTE; GLuint handle = 0; glGenTextures(1, &handle); glBindTexture(GL_TEXTURE_2D, handle); FGLDebug::LabelObject(GL_TEXTURE, handle, name); - glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, GL_RGBA, type, nullptr); + + GLenum dataformat, datatype; + switch (format) + { + case GL_RGBA8: dataformat = GL_RGBA; datatype = GL_UNSIGNED_BYTE; break; + 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_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_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"); + } + + glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, dataformat, datatype, data); 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_WRAP_S, GL_CLAMP_TO_EDGE); @@ -300,6 +373,17 @@ GLuint FGLRenderBuffers::Create2DTexture(const FString &name, GLuint format, int return handle; } +GLuint FGLRenderBuffers::Create2DMultisampleTexture(const FString &name, GLuint format, int width, int height, int samples, bool fixedSampleLocations) +{ + GLuint handle = 0; + glGenTextures(1, &handle); + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, handle); + FGLDebug::LabelObject(GL_TEXTURE, handle, name); + glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, format, width, height, fixedSampleLocations); + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0); + return handle; +} + //========================================================================== // // Creates a render buffer @@ -347,34 +431,22 @@ GLuint FGLRenderBuffers::CreateFrameBuffer(const FString &name, GLuint colorbuff return handle; } -GLuint FGLRenderBuffers::CreateFrameBuffer(const FString &name, GLuint colorbuffer, GLuint depthstencil, bool colorIsARenderBuffer) +GLuint FGLRenderBuffers::CreateFrameBuffer(const FString &name, GLuint colorbuffer, GLuint depthstencil, bool multisample) { GLuint handle = 0; glGenFramebuffers(1, &handle); glBindFramebuffer(GL_FRAMEBUFFER, handle); FGLDebug::LabelObject(GL_FRAMEBUFFER, handle, name); - if (colorIsARenderBuffer) - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorbuffer); + if (multisample) + { + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, colorbuffer, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE, depthstencil, 0); + } else + { glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorbuffer, 0); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthstencil); - if (CheckFrameBufferCompleteness()) - ClearFrameBuffer(true, true); - return handle; -} - -GLuint FGLRenderBuffers::CreateFrameBuffer(const FString &name, GLuint colorbuffer, GLuint depth, GLuint stencil, bool colorIsARenderBuffer) -{ - GLuint handle = 0; - glGenFramebuffers(1, &handle); - glBindFramebuffer(GL_FRAMEBUFFER, handle); - FGLDebug::LabelObject(GL_FRAMEBUFFER, handle, name); - if (colorIsARenderBuffer) - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorbuffer); - else - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorbuffer, 0); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, stencil); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, depthstencil, 0); + } if (CheckFrameBufferCompleteness()) ClearFrameBuffer(true, true); return handle; @@ -394,22 +466,23 @@ bool FGLRenderBuffers::CheckFrameBufferCompleteness() FailedCreate = true; -#if 0 - FString error = "glCheckFramebufferStatus failed: "; - switch (result) + if (gl_debug_level > 0) { - default: error.AppendFormat("error code %d", (int)result); break; - case GL_FRAMEBUFFER_UNDEFINED: error << "GL_FRAMEBUFFER_UNDEFINED"; break; - case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: error << "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT"; break; - case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: error << "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"; break; - case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: error << "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER"; break; - case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: error << "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER"; break; - case GL_FRAMEBUFFER_UNSUPPORTED: error << "GL_FRAMEBUFFER_UNSUPPORTED"; break; - case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: error << "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE"; break; - case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS: error << "GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS"; break; + FString error = "glCheckFramebufferStatus failed: "; + switch (result) + { + default: error.AppendFormat("error code %d", (int)result); break; + case GL_FRAMEBUFFER_UNDEFINED: error << "GL_FRAMEBUFFER_UNDEFINED"; break; + case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: error << "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT"; break; + case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: error << "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"; break; + case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: error << "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER"; break; + case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: error << "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER"; break; + case GL_FRAMEBUFFER_UNSUPPORTED: error << "GL_FRAMEBUFFER_UNSUPPORTED"; break; + case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: error << "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE"; break; + case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS: error << "GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS"; break; + } + Printf("%s\n", error.GetChars()); } - I_FatalError(error); -#endif return false; } @@ -482,6 +555,21 @@ void FGLRenderBuffers::BindSceneFB() glBindFramebuffer(GL_FRAMEBUFFER, mSceneFB); } +//========================================================================== +// +// Binds the depth texture to the specified texture unit +// +//========================================================================== + +void FGLRenderBuffers::BindSceneDepthTexture(int index) +{ + glActiveTexture(GL_TEXTURE0 + index); + if (mSamples > 1) + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mSceneDepthStencil); + else + glBindTexture(GL_TEXTURE_2D, mSceneDepthStencil); +} + //========================================================================== // // Binds the current scene/effect/hud texture to the specified texture unit diff --git a/src/gl/renderer/gl_renderbuffers.h b/src/gl/renderer/gl_renderbuffers.h index 08303a912e..32430f2ed4 100644 --- a/src/gl/renderer/gl_renderbuffers.h +++ b/src/gl/renderer/gl_renderbuffers.h @@ -23,6 +23,7 @@ public: bool Setup(int width, int height, int sceneWidth, int sceneHeight); void BindSceneFB(); + void BindSceneDepthTexture(int index); void BlitSceneToTexture(); void BindCurrentTexture(int index); @@ -35,24 +36,38 @@ public: enum { NumBloomLevels = 4 }; FGLBloomTextureLevel BloomLevels[NumBloomLevels]; + // Ambient occlusion buffers + GLuint AmbientTexture0 = 0; + GLuint AmbientTexture1 = 0; + GLuint AmbientFB0 = 0; + GLuint AmbientFB1 = 0; + int AmbientWidth = 0; + int AmbientHeight = 0; + GLuint AmbientRandomTexture = 0; + static bool IsEnabled(); int GetWidth() const { return mWidth; } int GetHeight() const { return mHeight; } + int GetSceneWidth() const { return mSceneWidth; } + int GetSceneHeight() const { return mSceneHeight; } + private: void ClearScene(); void ClearPipeline(); void ClearBloom(); + void ClearAmbientOcclusion(); void CreateScene(int width, int height, int samples); void CreatePipeline(int width, int height); void CreateBloom(int width, int height); - GLuint Create2DTexture(const FString &name, GLuint format, int width, int height); + void CreateAmbientOcclusion(int width, int height); + 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 CreateFrameBuffer(const FString &name, GLuint colorbuffer); - GLuint CreateFrameBuffer(const FString &name, GLuint colorbuffer, GLuint depthstencil, bool colorIsARenderBuffer); - GLuint CreateFrameBuffer(const FString &name, GLuint colorbuffer, GLuint depth, GLuint stencil, bool colorIsARenderBuffer); + GLuint CreateFrameBuffer(const FString &name, GLuint colorbuffer, GLuint depthstencil, bool multisample); bool CheckFrameBufferCompleteness(); void ClearFrameBuffer(bool stencil, bool depth); void DeleteTexture(GLuint &handle); @@ -63,8 +78,8 @@ private: int mHeight = 0; int mSamples = 0; int mMaxSamples = 0; - int mBloomWidth = 0; - int mBloomHeight = 0; + int mSceneWidth = 0; + int mSceneHeight = 0; static const int NumPipelineTextures = 2; int mCurrentPipelineTexture = 0; @@ -72,8 +87,6 @@ private: // Buffers for the scene GLuint mSceneMultisample = 0; GLuint mSceneDepthStencil = 0; - GLuint mSceneDepth = 0; - GLuint mSceneStencil = 0; GLuint mSceneFB = 0; // Effect/HUD buffers diff --git a/src/gl/shaders/gl_ambientshader.cpp b/src/gl/shaders/gl_ambientshader.cpp index 6b8c9cc485..f3b6eced67 100644 --- a/src/gl/shaders/gl_ambientshader.cpp +++ b/src/gl/shaders/gl_ambientshader.cpp @@ -49,22 +49,24 @@ #include "gl/system/gl_cvars.h" #include "gl/shaders/gl_ambientshader.h" -void FLinearDepthShader::Bind() +void FLinearDepthShader::Bind(bool multisample) { - if (!mShader) + auto &shader = mShader[multisample]; + if (!shader) { - mShader.Compile(FShaderProgram::Vertex, "shaders/glsl/screenquad.vp", "", 330); - mShader.Compile(FShaderProgram::Fragment, "shaders/glsl/lineardepth.fp", "", 330); - mShader.SetFragDataLocation(0, "FragColor"); - mShader.Link("shaders/glsl/lineardepth"); - mShader.SetAttribLocation(0, "PositionInProjection"); - DepthTexture.Init(mShader, "DepthTexture"); - LinearizeDepthA.Init(mShader, "LinearizeDepthA"); - LinearizeDepthB.Init(mShader, "LinearizeDepthB"); - InverseDepthRangeA.Init(mShader, "InverseDepthRangeA"); - InverseDepthRangeB.Init(mShader, "InverseDepthRangeB"); + shader.Compile(FShaderProgram::Vertex, "shaders/glsl/screenquad.vp", "", 330); + shader.Compile(FShaderProgram::Fragment, "shaders/glsl/lineardepth.fp", multisample ? "#define MULTISAMPLE\n" : "", 330); + shader.SetFragDataLocation(0, "FragColor"); + shader.Link("shaders/glsl/lineardepth"); + shader.SetAttribLocation(0, "PositionInProjection"); + DepthTexture[multisample].Init(shader, "DepthTexture"); + SampleCount[multisample].Init(shader, "SampleCount"); + LinearizeDepthA[multisample].Init(shader, "LinearizeDepthA"); + LinearizeDepthB[multisample].Init(shader, "LinearizeDepthB"); + InverseDepthRangeA[multisample].Init(shader, "InverseDepthRangeA"); + InverseDepthRangeB[multisample].Init(shader, "InverseDepthRangeB"); } - mShader.Bind(); + shader.Bind(); } void FSSAOShader::Bind() diff --git a/src/gl/shaders/gl_ambientshader.h b/src/gl/shaders/gl_ambientshader.h index 419ca939e2..5f9ef630b5 100644 --- a/src/gl/shaders/gl_ambientshader.h +++ b/src/gl/shaders/gl_ambientshader.h @@ -6,16 +6,17 @@ class FLinearDepthShader { public: - void Bind(); + void Bind(bool multisample); - FBufferedUniformSampler DepthTexture; - FBufferedUniform1f LinearizeDepthA; - FBufferedUniform1f LinearizeDepthB; - FBufferedUniform1f InverseDepthRangeA; - FBufferedUniform1f InverseDepthRangeB; + FBufferedUniformSampler DepthTexture[2]; + FBufferedUniform1i SampleCount[2]; + FBufferedUniform1f LinearizeDepthA[2]; + FBufferedUniform1f LinearizeDepthB[2]; + FBufferedUniform1f InverseDepthRangeA[2]; + FBufferedUniform1f InverseDepthRangeB[2]; private: - FShaderProgram mShader; + FShaderProgram mShader[2]; }; class FSSAOShader diff --git a/wadsrc/static/shaders/glsl/lineardepth.fp b/wadsrc/static/shaders/glsl/lineardepth.fp index f61bb39955..31df9dc321 100644 --- a/wadsrc/static/shaders/glsl/lineardepth.fp +++ b/wadsrc/static/shaders/glsl/lineardepth.fp @@ -2,7 +2,12 @@ in vec2 TexCoord; out vec4 FragColor; +#if defined(MULTISAMPLE) +uniform sampler2DMS DepthTexture; +uniform int SampleCount; +#else uniform sampler2D DepthTexture; +#endif uniform float LinearizeDepthA; uniform float LinearizeDepthB; uniform float InverseDepthRangeA; @@ -10,7 +15,21 @@ uniform float InverseDepthRangeB; void main() { +#if defined(MULTISAMPLE) + ivec2 texSize = textureSize(DepthTexture); + ivec2 ipos = ivec2(TexCoord * vec2(texSize)); + float depth = 0.0; + for (int i = 0; i < SampleCount; i++) + depth += texelFetch(DepthTexture, ipos, i).x; + depth /= float(SampleCount); +#else + /*ivec2 texSize = textureSize(DepthTexture, 0); + ivec2 ipos = ivec2(TexCoord * vec2(texSize)); + if (ipos.x < 0) ipos.x += texSize.x; + if (ipos.y < 0) ipos.y += texSize.y; + float depth = texelFetch(DepthTexture, ipos, 0).x;*/ float depth = texture(DepthTexture, TexCoord).x; +#endif float normalizedDepth = clamp(InverseDepthRangeA * depth + InverseDepthRangeB, 0.0, 1.0); FragColor = vec4(1.0 / (normalizedDepth * LinearizeDepthA + LinearizeDepthB), 0.0, 0.0, 1.0); }