From 3c3afb1fcc38a60f42424b5fbb49b5b2df24256b Mon Sep 17 00:00:00 2001 From: Green Sky Date: Thu, 1 Oct 2020 23:01:45 +0200 Subject: [PATCH] fix blur rendertask --- .../src/mm/opengl/shader.cpp | 2 +- .../src/mm/opengl/render_tasks/blur.cpp | 113 +++++++++++++----- .../src/mm/opengl/render_tasks/blur.hpp | 20 +++- framework/opengl_renderer/test/CMakeLists.txt | 2 + .../test/blur_render_task_test.cpp | 61 +++++++--- 5 files changed, 148 insertions(+), 50 deletions(-) diff --git a/framework/opengl_primitives/src/mm/opengl/shader.cpp b/framework/opengl_primitives/src/mm/opengl/shader.cpp index fa5c6f4..0f8459d 100644 --- a/framework/opengl_primitives/src/mm/opengl/shader.cpp +++ b/framework/opengl_primitives/src/mm/opengl/shader.cpp @@ -108,7 +108,7 @@ uint32_t Shader::compile(uint32_t type, const std::string& source) { glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length); char* msg = (char*) alloca(length * sizeof(char)); glGetShaderInfoLog(id, length, &length, msg); - LOG_ERROR("failed to compile {} Shader: {}", type == GL_VERTEX_SHADER ? "vertex" : "fragment", msg); + LOG_ERROR("failed to compile {} Shader: {}\n source: {}", type == GL_VERTEX_SHADER ? "vertex" : "fragment", msg, source); return 0; } diff --git a/framework/opengl_renderer/src/mm/opengl/render_tasks/blur.cpp b/framework/opengl_renderer/src/mm/opengl/render_tasks/blur.cpp index 7891eed..8baba02 100644 --- a/framework/opengl_renderer/src/mm/opengl/render_tasks/blur.cpp +++ b/framework/opengl_renderer/src/mm/opengl/render_tasks/blur.cpp @@ -36,8 +36,10 @@ Blur::Blur(Engine& engine) { _vao->unbind(); setupShaderFiles(); - _shader = Shader::createF(engine, vertexPath, fragmentPath); - assert(_shader != nullptr); + _hShader = Shader::createF(engine, vertexPath, fragmentHPath); + assert(_hShader != nullptr); + _vShader = Shader::createF(engine, vertexPath, fragmentVPath); + assert(_vShader != nullptr); } Blur::~Blur(void) { @@ -46,33 +48,47 @@ Blur::~Blur(void) { void Blur::render(Services::OpenGLRenderer& rs, Engine&) { ZoneScopedN("MM::OpenGL::RenderTasks::Blur::render"); - rs.targets[target_fbo]->bind(FrameBufferObject::W); + rs.targets[io_fbo]->bind(FrameBufferObject::W); glDisable(GL_DEPTH_TEST); + glDisable(GL_BLEND); // TODO: test - _shader->bind(); - _vertexBuffer->bind(GL_ARRAY_BUFFER); - _vao->bind(); + auto& rm_t = MM::ResourceManager::ref(); + auto tex_io = rm_t.get(entt::hashed_string::value(io_tex.c_str())); // TODO: perf problems + auto tex_temp = rm_t.get(entt::hashed_string::value(temp_tex.c_str())); // TODO: perf problems - rs.targets[src_fbo]->bind(FrameBufferObject::W); - { - _shader->setUniform1i("horizontal", 1); - rs.targets[src_fbo]->_texAttachments.front()->bind(0); + { // horizontal + rs.targets[temp_fbo]->bind(FrameBufferObject::W); + + _hShader->bind(); + _vertexBuffer->bind(GL_ARRAY_BUFFER); + _vao->bind(); + + glViewport(0, 0, tex_temp->width, tex_temp->height); + tex_io->bind(0); // read + + _hShader->setUniform2f("tex_offset", tex_offset); glDrawArrays(GL_TRIANGLES, 0, 6); } - rs.targets[target_fbo]->bind(FrameBufferObject::W); - { - _shader->setUniform1i("horizontal", 0); + { // vertical + rs.targets[io_fbo]->bind(FrameBufferObject::W); + + _vShader->bind(); + _vertexBuffer->bind(GL_ARRAY_BUFFER); + _vao->bind(); + + glViewport(0, 0, tex_io->width, tex_io->height); + tex_temp->bind(0); // read + + _vShader->setUniform2f("tex_offset", tex_offset); glDrawArrays(GL_TRIANGLES, 0, 6); } _vao->unbind(); _vertexBuffer->unbind(GL_ARRAY_BUFFER); - _shader->unbind(); - - rs.targets[src_fbo]->clear(0.f, 0.f, 0.f, 1.f); + _vShader->unbind(); } void Blur::setupShaderFiles(void) { @@ -84,14 +100,16 @@ R"( #endif in vec2 _vertexPosition; -out vec2 _tex; +out vec2 _tex_uv; void main() { gl_Position = vec4(_vertexPosition, 0, 1); - _tex = vec2(_vertexPosition.x * 0.5 + 0.5, _vertexPosition.y * 0.5 + 0.5); + _tex_uv = _vertexPosition * 0.5 + 0.5; })") - FS_CONST_MOUNT_FILE(fragmentPath, + // TODO: deduplicate + + FS_CONST_MOUNT_FILE(fragmentHPath, GLSL_VERSION_STRING R"( #ifdef GL_ES @@ -99,35 +117,70 @@ R"( #endif uniform sampler2D tex0; +in vec2 _tex_uv; -in vec2 _tex; - -uniform bool horizontal; +//uniform bool horizontal; +const bool horizontal = true; +uniform vec2 tex_offset; const float weight[5] = float[] (0.227027, 0.1945946, 0.1216216, 0.054054, 0.016216); out vec4 _out_color; void main() { - vec2 tex_offset = vec2(1.0) / vec2(textureSize(tex0, 0)); // gets size of single texel - vec3 result = texture(tex0, _tex).rgb * weight[0]; // current fragment's contribution + //vec2 tex_offset = vec2(1.0) / vec2(textureSize(tex0, 0)); // gets size of single texel + vec3 result = texture(tex0, _tex_uv).rgb * weight[0]; // current fragment's contribution if (horizontal) { for (int i = 1; i < 5; i++) { - result += texture(tex0, _tex + vec2(tex_offset.x * float(i), 0.0)).rgb * weight[i]; - result += texture(tex0, _tex - vec2(tex_offset.x * float(i), 0.0)).rgb * weight[i]; + result += texture(tex0, _tex_uv + vec2(tex_offset.x * float(i), 0.0)).rgb * weight[i]; + result += texture(tex0, _tex_uv - vec2(tex_offset.x * float(i), 0.0)).rgb * weight[i]; } } else { for (int i = 1; i < 5; i++) { - result += texture(tex0, _tex + vec2(0.0, tex_offset.y * float(i))).rgb * weight[i]; - result += texture(tex0, _tex - vec2(0.0, tex_offset.y * float(i))).rgb * weight[i]; + result += texture(tex0, _tex_uv + vec2(0.0, tex_offset.y * float(i))).rgb * weight[i]; + result += texture(tex0, _tex_uv - vec2(0.0, tex_offset.y * float(i))).rgb * weight[i]; } } _out_color = vec4(result, 1.0); +})") - //float brightness = dot(gl_FragColor.rgb, vec3(0.2126, 0.7152, 0.0722)); - //if (brightness > 1.0) + FS_CONST_MOUNT_FILE(fragmentVPath, +GLSL_VERSION_STRING +R"( +#ifdef GL_ES + precision mediump float; +#endif + +uniform sampler2D tex0; +in vec2 _tex_uv; + +//uniform bool horizontal; +const bool horizontal = false; +uniform vec2 tex_offset; + +const float weight[5] = float[] (0.227027, 0.1945946, 0.1216216, 0.054054, 0.016216); + +out vec4 _out_color; + +void main() { + //vec2 tex_offset = vec2(1.0) / vec2(textureSize(tex0, 0)); // gets size of single texel + vec3 result = texture(tex0, _tex_uv).rgb * weight[0]; // current fragment's contribution + + if (horizontal) { + for (int i = 1; i < 5; i++) { + result += texture(tex0, _tex_uv + vec2(tex_offset.x * float(i), 0.0)).rgb * weight[i]; + result += texture(tex0, _tex_uv - vec2(tex_offset.x * float(i), 0.0)).rgb * weight[i]; + } + } else { + for (int i = 1; i < 5; i++) { + result += texture(tex0, _tex_uv + vec2(0.0, tex_offset.y * float(i))).rgb * weight[i]; + result += texture(tex0, _tex_uv - vec2(0.0, tex_offset.y * float(i))).rgb * weight[i]; + } + } + + _out_color = vec4(result, 1.0); })") } diff --git a/framework/opengl_renderer/src/mm/opengl/render_tasks/blur.hpp b/framework/opengl_renderer/src/mm/opengl/render_tasks/blur.hpp index 1e3122e..29c59a5 100644 --- a/framework/opengl_renderer/src/mm/opengl/render_tasks/blur.hpp +++ b/framework/opengl_renderer/src/mm/opengl/render_tasks/blur.hpp @@ -3,6 +3,8 @@ #include "../render_task.hpp" #include +#include + // fwd namespace MM::OpenGL { class Shader; @@ -12,9 +14,11 @@ namespace MM::OpenGL { namespace MM::OpenGL::RenderTasks { + // this task expects to read and write to textures class Blur : public RenderTask { private: - std::shared_ptr _shader; + std::shared_ptr _hShader; + std::shared_ptr _vShader; std::unique_ptr _vertexBuffer; std::unique_ptr _vao; @@ -26,10 +30,18 @@ namespace MM::OpenGL::RenderTasks { public: const char* vertexPath = "shader/blur_render_task/vert.glsl"; - const char* fragmentPath = "shader/blur_render_task/frag.glsl"; + const char* fragmentHPath = "shader/blur_render_task/frag_h.glsl"; + const char* fragmentVPath = "shader/blur_render_task/frag_v.glsl"; - std::string target_fbo = "blur_out"; - std::string src_fbo = "blur_in"; + std::string io_fbo = "blur_io"; + std::string temp_fbo = "blur_temp"; + + // bc of it beeing a 2 pass, we need to flipflop + std::string io_tex = "blur_io"; + std::string temp_tex = "blur_temp"; + + // determines the kernel lookup offset. "ideal" is 1/tex_size + glm::vec2 tex_offset {0.001f, 0.001f}; private: void setupShaderFiles(void); diff --git a/framework/opengl_renderer/test/CMakeLists.txt b/framework/opengl_renderer/test/CMakeLists.txt index e35c8bb..c1d8d11 100644 --- a/framework/opengl_renderer/test/CMakeLists.txt +++ b/framework/opengl_renderer/test/CMakeLists.txt @@ -107,6 +107,8 @@ target_link_libraries(blur_render_task_test simple_scene simple_rect_render_task blur_render_task + copy_to_fb_render_task + clear_render_task imgui_service imgui_render_task diff --git a/framework/opengl_renderer/test/blur_render_task_test.cpp b/framework/opengl_renderer/test/blur_render_task_test.cpp index a36fda1..d998b9b 100644 --- a/framework/opengl_renderer/test/blur_render_task_test.cpp +++ b/framework/opengl_renderer/test/blur_render_task_test.cpp @@ -1,3 +1,5 @@ +#include "mm/opengl/render_tasks/clear.hpp" +#include "mm/opengl/render_tasks/copy_to_fb.hpp" #include #include @@ -20,6 +22,7 @@ #include #include +#include #include @@ -51,28 +54,56 @@ TEST(blur_render_task, it) { auto& rs = engine.addService(); ASSERT_TRUE(engine.enableService()); - rs.addRenderTask(engine).target_fbo = "game_view"; + //rs.addRenderTask(engine).target_fbo = "game_view"; - MM::OpenGL::RenderTasks::SimpleRect* bsrr_rend_ptr = &rs.addRenderTask(engine); - bsrr_rend_ptr->target_fbo = "blur_in"; + rs.addRenderTask(engine).target_fbo = "blur_io"; - MM::OpenGL::RenderTasks::Blur* blur_rend_ptr = &rs.addRenderTask(engine); - blur_rend_ptr->target_fbo = "display"; + MM::OpenGL::RenderTasks::SimpleRect& bsrr_rend = rs.addRenderTask(engine); + bsrr_rend.target_fbo = "blur_io"; + + MM::OpenGL::RenderTasks::Blur& blur_rend = rs.addRenderTask(engine); + blur_rend.io_tex = "blur_io"; + blur_rend.temp_tex = "blur_temp"; + blur_rend.io_fbo = "blur_io"; + blur_rend.temp_fbo = "blur_temp"; + + // render to display + auto& ctfb = rs.addRenderTask(engine); + ctfb.src_tex = "blur_io"; + ctfb.target_fbo = "display"; rs.addRenderTask(engine); + auto [w, h] = sdl_ss.getWindowSize(); + auto& rm_t = MM::ResourceManager::ref(); + { // setup textures + rm_t.load( + "blur_io", + GL_RGB, + w, h, + GL_RGB, GL_UNSIGNED_BYTE + ); - { - auto [w, h] = sdl_ss.getWindowSize(); + rm_t.load( + "blur_temp", + GL_RGB, + w, h, + GL_RGB, GL_UNSIGNED_BYTE + ); + } - rs.targets["game_view"] = MM::OpenGL::FBOBuilder::start() - .attachTexture(MM::OpenGL::Texture::createEmpty(GL_RGB, w, h, GL_RGB, GL_UNSIGNED_BYTE)) + + { // setup fbo s + //rs.targets["game_view"] = MM::OpenGL::FBOBuilder::start() + //.attachTexture(MM::OpenGL::Texture::createEmpty(GL_RGB, w, h, GL_RGB, GL_UNSIGNED_BYTE)) + //.finish(); + rs.targets["blur_io"] = MM::OpenGL::FBOBuilder::start() + .attachTexture(rm_t.get("blur_io"_hs)) + .setResize(true) .finish(); - rs.targets["blur_in"] = MM::OpenGL::FBOBuilder::start() - .attachTexture(MM::OpenGL::Texture::createEmpty(GL_RGB, w, h, GL_RGB, GL_UNSIGNED_BYTE)) - .finish(); - rs.targets["blur_out"] = MM::OpenGL::FBOBuilder::start() - .attachTexture(MM::OpenGL::Texture::createEmpty(GL_RGB, w, h, GL_RGB, GL_UNSIGNED_BYTE)) + rs.targets["blur_temp"] = MM::OpenGL::FBOBuilder::start() + .attachTexture(rm_t.get("blur_temp"_hs)) + .setResize(true) .finish(); } @@ -103,7 +134,7 @@ TEST(blur_render_task, it) { engine.addUpdate( [&](MM::Engine&) { - ImGui::ColorEdit4("rect_col", &bsrr_rend_ptr->default_color[0]); + ImGui::ColorEdit4("rect_col", &bsrr_rend.default_color[0]); } );