From a2244e87ad74b63b4c45f60cd6d99081125b3678 Mon Sep 17 00:00:00 2001 From: Tleety Date: Thu, 10 Mar 2016 12:18:06 +0100 Subject: [PATCH] WIP, trying to get blur to work with mipmaps --- include/Engine/Rendering/DrawBloomPass.h | 6 +- include/Engine/Rendering/FrameBuffer.h | 15 ++- resources/Shaders/Gaussian_horiz.frag.glsl | 5 +- resources/Shaders/Gaussian_vert.frag.glsl | 5 +- src/Engine/Rendering/DrawBloomPass.cpp | 120 ++++++++++++------ src/Engine/Rendering/FrameBuffer.cpp | 5 +- src/Engine/Rendering/Util/CommonFunctions.cpp | 3 +- 7 files changed, 106 insertions(+), 53 deletions(-) diff --git a/include/Engine/Rendering/DrawBloomPass.h b/include/Engine/Rendering/DrawBloomPass.h index e6a87c11..204f97d1 100644 --- a/include/Engine/Rendering/DrawBloomPass.h +++ b/include/Engine/Rendering/DrawBloomPass.h @@ -39,6 +39,7 @@ public: private: + void GaussianLodPass(GLuint mipMap, GLuint texture); Texture* m_BlackTexture; Model* m_ScreenQuad; @@ -47,12 +48,13 @@ private: //const LightCullingPass* m_LightCullingPass int m_Iterations; int m_Quality = 0; + int m_BloomLod = 4; GLuint m_GaussianTexture_horiz = 0; GLuint m_GaussianTexture_vert = 0; - FrameBuffer m_GaussianFrameBuffer_horiz; - FrameBuffer m_GaussianFrameBuffer_vert; + FrameBuffer* m_GaussianFrameBuffer_horiz = nullptr; + FrameBuffer* m_GaussianFrameBuffer_vert = nullptr; ShaderProgram* m_GaussianProgram_horiz; ShaderProgram* m_GaussianProgram_vert; diff --git a/include/Engine/Rendering/FrameBuffer.h b/include/Engine/Rendering/FrameBuffer.h index e9171894..1b4f6012 100644 --- a/include/Engine/Rendering/FrameBuffer.h +++ b/include/Engine/Rendering/FrameBuffer.h @@ -7,11 +7,12 @@ class BufferResource { public: - BufferResource(GLuint* resourceHandle, GLenum resourceType, GLenum attachment); + BufferResource(GLuint* resourceHandle, GLenum resourceType, GLenum attachment, GLuint mipMapLod); GLuint* m_ResourceHandle; GLenum m_ResourceType; GLenum m_Attachment; + GLuint m_MipMapLod = 0; private: }; @@ -20,15 +21,15 @@ template class ResourceType : public BufferResource { public: - ResourceType(GLuint* resourceHandle, GLenum attachment) - : BufferResource(resourceHandle, RESOURCETYPE, attachment) { } + ResourceType(GLuint* resourceHandle, GLenum attachment, GLuint mipMapLod) + : BufferResource(resourceHandle, RESOURCETYPE, attachment, mipMapLod) { } }; class Texture2D : public ResourceType { public: - Texture2D(GLuint* resourceHandle, GLenum attachment) - : ResourceType(resourceHandle, attachment) { }; + Texture2D(GLuint* resourceHandle, GLenum attachment, GLuint mipMapLod = 0) + : ResourceType(resourceHandle, attachment, mipMapLod) { }; ~Texture2D(); }; @@ -37,7 +38,7 @@ class RenderBuffer : public ResourceType { public: RenderBuffer(GLuint* resourceHandle, GLenum attachment) - : ResourceType(resourceHandle, attachment) + : ResourceType(resourceHandle, attachment, 0) { }; ~RenderBuffer(); @@ -47,7 +48,7 @@ class Texture2DArray : public ResourceType { public: Texture2DArray(GLuint* resourceHandle, GLenum attachment) - : ResourceType(resourceHandle, attachment) + : ResourceType(resourceHandle, attachment, 0) { }; ~Texture2DArray(); diff --git a/resources/Shaders/Gaussian_horiz.frag.glsl b/resources/Shaders/Gaussian_horiz.frag.glsl index 8a306ec2..06426ed3 100644 --- a/resources/Shaders/Gaussian_horiz.frag.glsl +++ b/resources/Shaders/Gaussian_horiz.frag.glsl @@ -2,6 +2,7 @@ #extension GL_EXT_gpu_shader4 : enable layout (binding = 0) uniform sampler2D Texture; +uniform int Lod; in VertexData{ vec2 TextureCoordinate; @@ -10,12 +11,14 @@ in VertexData{ out vec4 fragmentColor; uniform float weight[5] = float[](0.227027, 0.1945946, 0.1216216, 0.054054, 0.016216); +//uniform float weight[3] = float[](0.265495, 0.226535, 0.140718); void main() { - vec2 tex_offset = 1.0 / textureSize2D(Texture, 0); + vec2 tex_offset = 1.0 / textureSize(Texture, Lod); vec3 center = texture(Texture, Input.TextureCoordinate).rgb; vec3 result = center * weight[0]; + for(int i = 1; i < 5; ++i) { vec4 eastFragments = texture(Texture, Input.TextureCoordinate + vec2(tex_offset.x * i, 0.0)); vec4 westFragments = texture(Texture, Input.TextureCoordinate - vec2(tex_offset.x * i, 0.0)); diff --git a/resources/Shaders/Gaussian_vert.frag.glsl b/resources/Shaders/Gaussian_vert.frag.glsl index 921ba55a..3924450a 100644 --- a/resources/Shaders/Gaussian_vert.frag.glsl +++ b/resources/Shaders/Gaussian_vert.frag.glsl @@ -2,6 +2,7 @@ #extension GL_EXT_gpu_shader4 : enable layout (binding = 0) uniform sampler2D Texture; +uniform int Lod; in VertexData{ vec2 TextureCoordinate; @@ -10,12 +11,14 @@ in VertexData{ out vec4 fragmentColor; uniform float weight[5] = float[](0.227027, 0.1945946, 0.1216216, 0.054054, 0.016216); +//uniform float weight[3] = float[](0.265495, 0.226535, 0.140718); void main() { - vec2 tex_offset = 1.0 / textureSize2D(Texture, 0); + vec2 tex_offset = 1.0 / textureSize(Texture, Lod); vec3 center = texture(Texture, Input.TextureCoordinate).rgb; vec3 result = center * weight[0]; + for(int i = 1; i < 5; ++i) { vec4 northFragments = texture(Texture, Input.TextureCoordinate + vec2(0.0, tex_offset.y * i)); vec4 southFragments = texture(Texture, Input.TextureCoordinate - vec2(0.0, tex_offset.y * i)); diff --git a/src/Engine/Rendering/DrawBloomPass.cpp b/src/Engine/Rendering/DrawBloomPass.cpp index 4172118c..f30734db 100644 --- a/src/Engine/Rendering/DrawBloomPass.cpp +++ b/src/Engine/Rendering/DrawBloomPass.cpp @@ -66,18 +66,31 @@ void DrawBloomPass::InitializeShaderPrograms() void DrawBloomPass::InitializeBuffers() { - CommonFunctions::GenerateTexture(&m_GaussianTexture_horiz, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT); + CommonFunctions::GenerateMipMapTexture( + &m_GaussianTexture_horiz, GL_CLAMP_TO_EDGE, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height) + , GL_RGB, GL_FLOAT, m_BloomLod); + CommonFunctions::GenerateMipMapTexture( + &m_GaussianTexture_vert, GL_CLAMP_TO_EDGE, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height) + , GL_RGB, GL_FLOAT, m_BloomLod); - if (m_GaussianFrameBuffer_horiz.GetHandle() == 0) { - m_GaussianFrameBuffer_horiz.AddResource(std::shared_ptr(new Texture2D(&m_GaussianTexture_horiz, GL_COLOR_ATTACHMENT0))); - } - m_GaussianFrameBuffer_horiz.Generate(); + if(m_GaussianFrameBuffer_horiz == nullptr) { + m_GaussianFrameBuffer_horiz = new FrameBuffer[m_BloomLod]; + } + if (m_GaussianFrameBuffer_vert == nullptr) { + m_GaussianFrameBuffer_vert = new FrameBuffer[m_BloomLod]; + } - CommonFunctions::GenerateTexture(&m_GaussianTexture_vert, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT); - if (m_GaussianFrameBuffer_vert.GetHandle() == 0) { - m_GaussianFrameBuffer_vert.AddResource(std::shared_ptr(new Texture2D(&m_GaussianTexture_vert, GL_COLOR_ATTACHMENT0))); - } - m_GaussianFrameBuffer_vert.Generate(); + for (int i = 0; i < m_BloomLod; i++) { + if(m_GaussianFrameBuffer_horiz[i].GetHandle() == 0) { + m_GaussianFrameBuffer_horiz[i].AddResource(std::shared_ptr(new Texture2D(&m_GaussianTexture_horiz, GL_COLOR_ATTACHMENT0, i))); + } + m_GaussianFrameBuffer_horiz[i].Generate(); + + if (m_GaussianFrameBuffer_vert[i].GetHandle() == 0) { + m_GaussianFrameBuffer_vert[i].AddResource(std::shared_ptr(new Texture2D(&m_GaussianTexture_vert, GL_COLOR_ATTACHMENT0, i))); + } + m_GaussianFrameBuffer_vert[i].Generate(); + } } @@ -87,22 +100,53 @@ void DrawBloomPass::ClearBuffer() return; } GLERROR("PRE"); - m_GaussianFrameBuffer_horiz.Bind(); - glClearColor(0.f, 0.f, 0.f, 0.f); - glClear(GL_COLOR_BUFFER_BIT); - m_GaussianFrameBuffer_horiz.Unbind(); - m_GaussianFrameBuffer_vert.Bind(); - glClearColor(0.f, 0.f, 0.f, 0.f); - glClear(GL_COLOR_BUFFER_BIT); - m_GaussianFrameBuffer_vert.Unbind(); + for (int i = 0; i < m_BloomLod; i++) { + m_GaussianFrameBuffer_horiz[i].Bind(); + glClearColor(0.f, 0.f, 0.f, 0.f); + glClear(GL_COLOR_BUFFER_BIT); + m_GaussianFrameBuffer_horiz[i].Unbind(); + m_GaussianFrameBuffer_vert[i].Bind(); + glClearColor(0.f, 0.f, 0.f, 0.f); + glClear(GL_COLOR_BUFFER_BIT); + m_GaussianFrameBuffer_vert[i].Unbind(); + } + GLERROR("END"); } void DrawBloomPass::Draw(GLuint texture) +{ + if (m_Quality == 0) { + return; + } + + for (int i = 0; i < m_BloomLod; i++) { + GaussianLodPass(i, texture); + } +} + + +void DrawBloomPass::OnWindowResize() { if (m_Quality == 0) { return; } + CommonFunctions::GenerateMipMapTexture( + &m_GaussianTexture_vert, GL_CLAMP_TO_EDGE, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height) + , GL_RGB, GL_FLOAT, m_BloomLod); + CommonFunctions::GenerateMipMapTexture( + &m_GaussianTexture_horiz, GL_CLAMP_TO_EDGE, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height) + , GL_RGB, GL_FLOAT, m_BloomLod); + for (int i = 0; i < m_BloomLod; i++) { + m_GaussianFrameBuffer_vert[i].Generate(); + m_GaussianFrameBuffer_horiz[i].Generate(); + + } + +} + +void DrawBloomPass::GaussianLodPass(GLuint mipMap, GLuint texture) +{ GLERROR("DrawBloomPass::Draw: Pre"); DrawBloomPassState state; @@ -110,10 +154,14 @@ void DrawBloomPass::Draw(GLuint texture) GLuint shaderHandle_horiz = m_GaussianProgram_horiz->GetHandle(); GLuint shaderHandle_vert = m_GaussianProgram_vert->GetHandle(); - //Horizontal pass, first use the given texture then save it to the horizontal framebuffer. - m_GaussianFrameBuffer_horiz.Bind(); + m_GaussianFrameBuffer_horiz[mipMap].Bind(); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, mipMap); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, mipMap); m_GaussianProgram_horiz->Bind(); + glUniform1i(glGetUniformLocation(shaderHandle_horiz, "Lod"), mipMap); + + glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture); glBindVertexArray(m_ScreenQuad->VAO); @@ -123,10 +171,12 @@ void DrawBloomPass::Draw(GLuint texture) //Iterate some times to make it more gaussian. for (int i = 1; i < m_Iterations; i++) { //Vertical pass - m_GaussianFrameBuffer_vert.Bind(); + m_GaussianFrameBuffer_vert[mipMap].Bind(); m_GaussianProgram_vert->Bind(); + glUniform1i(glGetUniformLocation(shaderHandle_vert, "Lod"), mipMap); - glActiveTexture(GL_TEXTURE0); + + glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, m_GaussianTexture_horiz); glBindVertexArray(m_ScreenQuad->VAO); @@ -134,27 +184,29 @@ void DrawBloomPass::Draw(GLuint texture) glDrawElementsBaseVertex(GL_TRIANGLES, m_ScreenQuad->MaterialGroups()[0].material->EndIndex - m_ScreenQuad->MaterialGroups()[0].material->StartIndex +1 , GL_UNSIGNED_INT, 0, m_ScreenQuad->MaterialGroups()[0].material->StartIndex); //horizontal pass - m_GaussianFrameBuffer_vert.Unbind(); + m_GaussianFrameBuffer_vert[mipMap].Unbind(); - m_GaussianFrameBuffer_horiz.Bind(); + m_GaussianFrameBuffer_horiz[mipMap].Bind(); m_GaussianProgram_horiz->Bind(); + glUniform1i(glGetUniformLocation(shaderHandle_horiz, "Lod"), mipMap); - glActiveTexture(GL_TEXTURE0); + glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, m_GaussianTexture_vert); glBindVertexArray(m_ScreenQuad->VAO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ScreenQuad->ElementBuffer); glDrawElementsBaseVertex(GL_TRIANGLES, m_ScreenQuad->MaterialGroups()[0].material->EndIndex - m_ScreenQuad->MaterialGroups()[0].material->StartIndex +1 , GL_UNSIGNED_INT, 0, m_ScreenQuad->MaterialGroups()[0].material->StartIndex); - m_GaussianFrameBuffer_horiz.Unbind(); + m_GaussianFrameBuffer_horiz[mipMap].Unbind(); } //final vertical gaussian after the iterations are done - m_GaussianFrameBuffer_vert.Bind(); + m_GaussianFrameBuffer_vert[mipMap].Bind(); m_GaussianProgram_vert->Bind(); + glUniform1i(glGetUniformLocation(shaderHandle_vert, "Lod"), mipMap); - glActiveTexture(GL_TEXTURE0); + glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, m_GaussianTexture_horiz); glBindVertexArray(m_ScreenQuad->VAO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ScreenQuad->ElementBuffer); @@ -162,16 +214,6 @@ void DrawBloomPass::Draw(GLuint texture) , GL_UNSIGNED_INT, 0, m_ScreenQuad->MaterialGroups()[0].material->StartIndex); GLERROR("DrawBloomPass::Draw: END"); -} + m_GaussianFrameBuffer_vert[mipMap].Unbind(); - -void DrawBloomPass::OnWindowResize() -{ - if (m_Quality == 0) { - return; - } - CommonFunctions::GenerateTexture(&m_GaussianTexture_vert, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT); - m_GaussianFrameBuffer_vert.Generate(); - CommonFunctions::GenerateTexture(&m_GaussianTexture_horiz, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT); - m_GaussianFrameBuffer_horiz.Generate(); } diff --git a/src/Engine/Rendering/FrameBuffer.cpp b/src/Engine/Rendering/FrameBuffer.cpp index c94423ba..dfabb8a3 100644 --- a/src/Engine/Rendering/FrameBuffer.cpp +++ b/src/Engine/Rendering/FrameBuffer.cpp @@ -2,11 +2,12 @@ #include "Rendering/FrameBuffer.h" -BufferResource::BufferResource(GLuint* resourceHandle, GLenum resourceType, GLenum attachment) +BufferResource::BufferResource(GLuint* resourceHandle, GLenum resourceType, GLenum attachment, GLuint mipMapLod) { m_ResourceHandle = resourceHandle; m_ResourceType = resourceType; m_Attachment = attachment; + m_MipMapLod = mipMapLod; } Texture2D::~Texture2D() @@ -58,7 +59,7 @@ void FrameBuffer::Generate() for (auto it = m_Resources.begin(); it != m_Resources.end(); it++) { switch ((*it)->m_ResourceType) { case GL_TEXTURE_2D: - glFramebufferTexture2D(GL_FRAMEBUFFER, (*it)->m_Attachment, (*it)->m_ResourceType, *(*it)->m_ResourceHandle, 0); + glFramebufferTexture(GL_FRAMEBUFFER, (*it)->m_Attachment, *(*it)->m_ResourceHandle, (*it)->m_MipMapLod); GLERROR("FrameBuffer generate: glFramebufferTexture2D"); break; case GL_RENDERBUFFER: diff --git a/src/Engine/Rendering/Util/CommonFunctions.cpp b/src/Engine/Rendering/Util/CommonFunctions.cpp index e1344928..dac9fca3 100644 --- a/src/Engine/Rendering/Util/CommonFunctions.cpp +++ b/src/Engine/Rendering/Util/CommonFunctions.cpp @@ -28,7 +28,8 @@ void CommonFunctions::GenerateMipMapTexture(GLuint* texture, GLenum wrapping, gl glGenTextures(1, texture); glBindTexture(GL_TEXTURE_2D, *texture); glTexStorage2D(GL_TEXTURE_2D, numMipMaps, GL_RGBA8, dimensions.x, dimensions.y); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, dimensions.x, dimensions.y, format, type, texture); + //glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, dimensions.x, dimensions.y, format, type, NULL); + GLERROR("MipMap Texture glTexSubImage2D failed"); glGenerateMipmap(GL_TEXTURE_2D); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapping); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapping);