diff --git a/CMakeLists.txt b/CMakeLists.txt index c309943..9b52558 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.25) -set(BLT_GRAPHICS_VERSION 0.13.5) +set(BLT_GRAPHICS_VERSION 0.13.6) set(BLT_GRAPHICS_TEST_VERSION 0.0.1) project(BLT_WITH_GRAPHICS VERSION ${BLT_GRAPHICS_VERSION}) diff --git a/include/blt/gfx/renderer/batch_2d_renderer.h b/include/blt/gfx/renderer/batch_2d_renderer.h index c97eec3..8ce7337 100644 --- a/include/blt/gfx/renderer/batch_2d_renderer.h +++ b/include/blt/gfx/renderer/batch_2d_renderer.h @@ -174,6 +174,7 @@ namespace blt::gfx shader_t* square_shader = nullptr; shader_t* point_shader = nullptr; resource_manager& resources; + matrix_state_manager& state; // texture name -> draw info struct { @@ -209,10 +210,15 @@ namespace blt::gfx } public: - explicit batch_renderer_2d(resource_manager& resources, matrix_state_manager& state): resources(resources) + explicit batch_renderer_2d(resource_manager& resources, matrix_state_manager& state): resources(resources), state(state) { - engine = pp_engine_t::make_multi_pp(std::make_unique(), - std::make_unique(state)); + engine = pp_engine_t::make_multi_pp(std::make_unique(), + std::make_unique(state, frame_buffer_t::attachment_t::COLOR1), + std::make_unique(frame_buffer_t::attachment_t::COLOR1, + vec4{4, 4, 4, 1}), + std::make_unique(state, frame_buffer_t::attachment_t::COLOR1, 2, 2), + std::make_unique(state) + ); } void create(); diff --git a/include/blt/gfx/renderer/postprocess.h b/include/blt/gfx/renderer/postprocess.h index 61201b7..27c4c05 100644 --- a/include/blt/gfx/renderer/postprocess.h +++ b/include/blt/gfx/renderer/postprocess.h @@ -26,6 +26,7 @@ #include #include #include +#include namespace blt::gfx { @@ -33,6 +34,12 @@ namespace blt::gfx class pp_step_t; + enum class pp_request_t : u64 + { + BIND_BUFFER = 0x1, + CLEAR_BUFFER = 0x2 + }; + class pp_step_t { public: @@ -40,13 +47,17 @@ namespace blt::gfx {} // only called on render() - virtual void draw(pp_step_t&) + virtual void draw(frame_buffer_t&) {} // only called on bind() virtual void draw() {} + // called after rendering, provides previous framebuffer + virtual void post_draw(frame_buffer_t&) + {} + auto& getBuffer() { return draw_buffer; @@ -62,6 +73,11 @@ namespace blt::gfx return shader != nullptr; } + virtual bool requests(pp_request_t) + { + return true; + } + virtual ~pp_step_t() = default; protected: @@ -69,6 +85,25 @@ namespace blt::gfx std::unique_ptr shader; }; + class pp_in_place_t : public pp_step_t + { + public: + pp_in_place_t(frame_buffer_t::attachment_t from): from(from), to(from) + {} + + pp_in_place_t(frame_buffer_t::attachment_t from, frame_buffer_t::attachment_t to): from(from), to(to) + {} + + bool requests(blt::gfx::pp_request_t request) override + { + return static_cast(request) & ~(static_cast(pp_request_t::BIND_BUFFER) | static_cast(pp_request_t::CLEAR_BUFFER)); + } + + protected: + frame_buffer_t::attachment_t from; + frame_buffer_t::attachment_t to; + }; + class pp_render_target_t : public pp_step_t { public: @@ -82,10 +117,10 @@ namespace blt::gfx public: void create() override; - void draw(pp_step_t& previous) override; + void draw(frame_buffer_t& previous) override; }; - class pp_outline_target : public pp_step_t + class pp_outline_target_t : public pp_step_t { public: void create() override; @@ -101,12 +136,93 @@ namespace blt::gfx void create() override; - void draw(pp_step_t& previous) override; + void draw(frame_buffer_t& previous) override; private: matrix_state_manager& manager; }; + class pp_blur_step_base_t : public pp_step_t + { + public: + pp_blur_step_base_t(frame_buffer_t::attachment_t from, i32 x_blur = 2, i32 y_blur = 2): + from(from), to(from), x_blur(x_blur), y_blur(y_blur) + {} + + pp_blur_step_base_t(frame_buffer_t::attachment_t from, frame_buffer_t::attachment_t to, i32 x_blur = 2, i32 y_blur = 2): + from(from), to(to), x_blur(x_blur), y_blur(y_blur) + {} + + protected: + frame_buffer_t::attachment_t from; + frame_buffer_t::attachment_t to; + i32 x_blur; + i32 y_blur; + }; + + class pp_blur_step_t : public pp_blur_step_base_t + { + public: + pp_blur_step_t(frame_buffer_t::attachment_t from, i32 x_blur = 2, i32 y_blur = 2): pp_blur_step_base_t(from, x_blur, y_blur) + {} + + pp_blur_step_t(frame_buffer_t::attachment_t from, frame_buffer_t::attachment_t to, i32 x_blur = 2, i32 y_blur = 2): + pp_blur_step_base_t(from, to, x_blur, y_blur) + {} + + void create() override; + + void draw(frame_buffer_t& previous); + }; + + class pp_blur_step_inplace_t : public pp_blur_step_base_t + { + public: + pp_blur_step_inplace_t(matrix_state_manager& manager, frame_buffer_t::attachment_t from, i32 x_blur = 2, i32 y_blur = 2): + pp_blur_step_base_t(from, x_blur, y_blur), manager(manager) + {} + + pp_blur_step_inplace_t(matrix_state_manager& manager, frame_buffer_t::attachment_t from, frame_buffer_t::attachment_t to, i32 x_blur = 2, + i32 y_blur = 2): + pp_blur_step_base_t(from, to, x_blur, y_blur), manager(manager) + {} + + void create() override; + + void draw(frame_buffer_t& previous); + + void post_draw(frame_buffer_t& previous) override; + + bool requests(blt::gfx::pp_request_t request) override + { + return static_cast(request) & ~(static_cast(pp_request_t::BIND_BUFFER) | static_cast(pp_request_t::CLEAR_BUFFER)); + } + + private: + std::unique_ptr shader_pass; + matrix_state_manager& manager; + }; + + class pp_expansion_step_inplace_t : public pp_in_place_t + { + public: + pp_expansion_step_inplace_t(frame_buffer_t::attachment_t from, const vec4& multiplier = vec4{2,2,2,2}): + pp_in_place_t(from), multiplier(multiplier) + {} + + pp_expansion_step_inplace_t(frame_buffer_t::attachment_t from, frame_buffer_t::attachment_t to, + const vec4& multiplier = vec4{2,2,2,2}): + pp_in_place_t(from, to), multiplier(multiplier) + {} + + void create() override; + + void draw(frame_buffer_t& previous); + + private: + vec4 multiplier; + }; + class pp_engine_t { public: @@ -144,10 +260,14 @@ namespace blt::gfx (engine->addStep(std::move(steps)), ...); return std::unique_ptr(engine); } + + static void render_quad(); private: pp_engine_t() = default; + pp_step_t& find_last_frame_buffer(size_t index); + std::vector> steps; std::unique_ptr screen_vao; }; diff --git a/include/blt/gfx/renderer/shaders/pp_gaussian_blur.frag b/include/blt/gfx/renderer/shaders/pp_gaussian_blur.frag new file mode 100644 index 0000000..521579d --- /dev/null +++ b/include/blt/gfx/renderer/shaders/pp_gaussian_blur.frag @@ -0,0 +1,28 @@ +#ifdef __cplusplus +#include +const std::string shader_gaussian_blur_frag = R"(" +#version 300 es +precision mediump float; + +out vec4 FragColor; +in vec2 uv; +in vec2 pos; + +uniform sampler2D tex; +uniform ivec4 size; + +void main() { + vec2 texelSize = 1.0 / vec2(float(size.x), float(size.y)); + vec4 result = vec4(0.0, 0.0, 0.0, 0.0); + for (int x = -size.z; x <= size.z; ++x) { + for (int y = -size.w; y <= size.w; ++y) { + vec2 offset = (vec2(float(x), float(y)) * texelSize); + result += texture(tex, uv + offset); + } + } + //FragColor = result; + FragColor = result / vec4((float(size.z) * 2.0 + 1.0) * (float(size.w) * 2.0 + 1.0)); +} + +")"; +#endif \ No newline at end of file diff --git a/include/blt/gfx/renderer/shaders/pp_multiplier.frag b/include/blt/gfx/renderer/shaders/pp_multiplier.frag new file mode 100644 index 0000000..3e4cafb --- /dev/null +++ b/include/blt/gfx/renderer/shaders/pp_multiplier.frag @@ -0,0 +1,19 @@ +#ifdef __cplusplus +#include +const std::string shader_multiplier_frag = R"(" +#version 300 es +precision mediump float; + +out vec4 FragColor; +in vec2 uv; +in vec2 pos; + +uniform sampler2D tex; +uniform vec4 multiplier; + +void main() { + FragColor = normalize(texture(tex, uv) * multiplier); +} + +")"; +#endif \ No newline at end of file diff --git a/include/blt/gfx/renderer/shaders/pp_outline_step.frag b/include/blt/gfx/renderer/shaders/pp_outline_step.frag index fb4e2b6..825991b 100644 --- a/include/blt/gfx/renderer/shaders/pp_outline_step.frag +++ b/include/blt/gfx/renderer/shaders/pp_outline_step.frag @@ -19,38 +19,41 @@ float longest(vec3 v){ return max(v.r, max(v.b, v.g)); } -#define LINE_WEIGHT 3.0 +#define LINE_WEIGHT 1.0 void main() { - float dx = (1.0 / viewportSize.x) * LINE_WEIGHT; - float dy = (1.0 / viewportSize.y) * LINE_WEIGHT; - - vec2 uvCenter = uv; - vec2 uvRight = vec2(uvCenter.x + dx, uvCenter.y); - vec2 uvTop = vec2(uvCenter.x, uvCenter.y - dx); - vec2 uvTopRight = vec2(uvCenter.x + dx, uvCenter.y - dx); - - float mCenter = longest(texture(mask, uvCenter).rgb); - float mTop = longest(texture(mask, uvTop).rgb); - float mRight = longest(texture(mask, uvRight).rgb); - float mTopRight = longest(texture(mask, uvTopRight).rgb); - - float dT = abs(mCenter - mTop); - float dR = abs(mCenter - mRight); - float dTR = abs(mCenter - mTopRight); - - float delta = 0.0f; - delta = max(delta, dT); - delta = max(delta, dR); - delta = max(delta, dTR); - - vec4 outline = vec4(delta, delta, delta, 1.0); - vec4 albedo = texture(albedo, uv); - - if (delta <= 0.001) - FragColor = albedo; - else - FragColor = outline_color; +// float dx = (1.0 / viewportSize.x) * LINE_WEIGHT; +// float dy = (1.0 / viewportSize.y) * LINE_WEIGHT; +// +// vec2 uvCenter = uv; +// vec2 uvRight = vec2(uvCenter.x + dx, uvCenter.y); +// vec2 uvTop = vec2(uvCenter.x, uvCenter.y - dy); +// vec2 uvTopRight = vec2(uvCenter.x + dx, uvCenter.y - dy); +// +// float mCenter = longest(texture(mask, uvCenter).rgb); +// float mTop = longest(texture(mask, uvTop).rgb); +// float mRight = longest(texture(mask, uvRight).rgb); +// float mTopRight = longest(texture(mask, uvTopRight).rgb); +// +// float dT = abs(mCenter - mTop); +// float dR = abs(mCenter - mRight); +// float dTR = abs(mCenter - mTopRight); +// +// float delta = 0.0f; +// delta = max(delta, dT); +// delta = max(delta, dR); +// delta = max(delta, dTR); +// +// vec4 outline = vec4(delta, delta, delta, 1.0); +// vec4 albedo = texture(albedo, uv); +// +// if (delta <= 0.0) +// FragColor = albedo; +// else +// FragColor = outline_color; + FragColor = texture(albedo, uv); + if (FragColor.a == 0.0) + FragColor = texture(mask, uv); } ")"; diff --git a/include/blt/gfx/shader.h b/include/blt/gfx/shader.h index 37a7ead..cb2a383 100644 --- a/include/blt/gfx/shader.h +++ b/include/blt/gfx/shader.h @@ -116,6 +116,7 @@ namespace blt::gfx shader_base_t& setVec3(const std::string& name, const blt::vec3& vec); shader_base_t& setVec4(const std::string& name, const blt::vec4& vec); + shader_base_t& setVec4i(const std::string& name, const blt::vec4i& vec); shader_base_t& setVec2(const std::string& name, float x, float y); diff --git a/include/blt/gfx/texture.h b/include/blt/gfx/texture.h index 73d1e51..2f05a08 100644 --- a/include/blt/gfx/texture.h +++ b/include/blt/gfx/texture.h @@ -135,7 +135,7 @@ namespace blt::gfx } protected: - void setDefaults(GLint type) const; + void setDefaults(GLint type, GLint wrap = GL_REPEAT) const; inline void generateMipmaps() const { diff --git a/libraries/BLT b/libraries/BLT index 9b86278..943fb84 160000 --- a/libraries/BLT +++ b/libraries/BLT @@ -1 +1 @@ -Subproject commit 9b86278a2982d80fbac6f87045a182088e07afbe +Subproject commit 943fb842117cd698f75ffd7d13815622e4a6e128 diff --git a/src/blt/gfx/framebuffer.cpp b/src/blt/gfx/framebuffer.cpp index fd6db4a..a1d4a69 100644 --- a/src/blt/gfx/framebuffer.cpp +++ b/src/blt/gfx/framebuffer.cpp @@ -175,10 +175,9 @@ namespace blt::gfx { glBindFramebuffer(GL_READ_FRAMEBUFFER, fboID); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, draw.fboID); - glReadBuffer(static_cast(attachment_read)); -#ifdef glDrawBuffer - glDrawBuffer(static_cast(attachment_write)); -#endif + glReadBuffer(static_cast(attachment_read)); + GLenum buffers[] {static_cast(attachment_write)}; + glDrawBuffers(1, buffers); glBlitFramebuffer(srcX, srcY, width_, height_, destX, destY, draw.width_, draw.height_, GL_COLOR_BUFFER_BIT, filter); } @@ -186,6 +185,9 @@ namespace blt::gfx { glBindFramebuffer(GL_READ_FRAMEBUFFER, fboID); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, draw.fboID); + glReadBuffer(static_cast(attachment_t::DEPTH)); + GLenum buffers[] {static_cast(attachment_t::DEPTH)}; + glDrawBuffers(1, buffers); glBlitFramebuffer(srcX, srcY, width_, height_, destX, destY, draw.width_, draw.height_, GL_DEPTH_BUFFER_BIT, filter); } @@ -193,6 +195,9 @@ namespace blt::gfx { glBindFramebuffer(GL_READ_FRAMEBUFFER, fboID); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, draw.fboID); + glReadBuffer(static_cast(attachment_t::STENCIL)); + GLenum buffers[] {static_cast(attachment_t::STENCIL)}; + glDrawBuffers(1, buffers); glBlitFramebuffer(srcX, srcY, width_, height_, destX, destY, draw.width_, draw.height_, GL_STENCIL_BUFFER_BIT, filter); } @@ -202,6 +207,9 @@ namespace blt::gfx glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); //glReadBuffer(GL_COLOR_ATTACHMENT0); //glDrawBuffer(GL_COLOR_ATTACHMENT0); + glReadBuffer(static_cast(attachment_t::COLOR0)); + GLenum buffers[] {static_cast(attachment_t::COLOR0)}; + glDrawBuffers(1, buffers); glBlitFramebuffer(0, 0, width_, height_, 0, 0, width, height, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST); } diff --git a/src/blt/gfx/renderer/batch_2d_renderer.cpp b/src/blt/gfx/renderer/batch_2d_renderer.cpp index 2453f13..1a3173f 100644 --- a/src/blt/gfx/renderer/batch_2d_renderer.cpp +++ b/src/blt/gfx/renderer/batch_2d_renderer.cpp @@ -184,8 +184,6 @@ namespace blt::gfx glActiveTexture(GL_TEXTURE0); engine->bind(); - const GLenum buffers[]{GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1}; - glDrawBuffers(2, buffers); draw_objects(); glDisable(GL_DEPTH_TEST); @@ -295,7 +293,7 @@ namespace blt::gfx mat4x4 model; model.translate(point.pos.x(), point.pos.y(), 0.0f); - model.scale(point.scale, point.scale, 1); + model.scale(point.scale, point.scale, 1.0); point_shader->setVec4("color", render_info.color); point_shader->setVec4("use_texture", render_info.blend); diff --git a/src/blt/gfx/renderer/postprocess.cpp b/src/blt/gfx/renderer/postprocess.cpp index 8a19cd6..b5ed8a3 100644 --- a/src/blt/gfx/renderer/postprocess.cpp +++ b/src/blt/gfx/renderer/postprocess.cpp @@ -20,7 +20,10 @@ #include #include #include +#include +#include #include +#include #define __EMSCRIPTEN__ @@ -68,6 +71,17 @@ namespace blt::gfx step->create(); } + pp_step_t& pp_engine_t::find_last_frame_buffer(size_t index) + { + for (i64 i = static_cast(index); i >= 0; i--) + { + if (steps[i]->requests(pp_request_t::BIND_BUFFER)) + return *steps[i]; + } + BLT_FATAL("We reached the end trying to find a previous frame buffer, unable to do so! Please ensure this in-place step has a framebuffer!"); + std::exit(1); + } + void pp_engine_t::render() { screen_vao->bind(); @@ -75,13 +89,18 @@ namespace blt::gfx { if (index == 0) continue; - auto& previous = steps[index - 1]; - step->getBuffer().bind(frame_buffer_t::draw_t::BOTH); - step->draw(*previous); + auto& previous = find_last_frame_buffer(index - 1); + if (step->requests(pp_request_t::BIND_BUFFER)) + step->getBuffer().bind(); + else + previous.getBuffer().bind(); + if (step->requests(pp_request_t::CLEAR_BUFFER)) + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + step->draw(previous.getBuffer()); if (step->hasShader()) step->getShader().bind(); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); + render_quad(); + step->post_draw(previous.getBuffer()); } glBindTexture(GL_TEXTURE_2D, 0); frame_buffer_t::unbind(); @@ -108,20 +127,27 @@ namespace blt::gfx void pp_engine_t::bind() { - steps.front()->draw(); steps.front()->getBuffer().bind(); + steps.front()->draw(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } + void pp_engine_t::render_quad() + { + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); + } + void pp_to_screen_step_t::create() { shader = pp_engine_t::createShader(shader_pp_screen_frag); } - void pp_to_screen_step_t::draw(pp_step_t& previous) + void pp_to_screen_step_t::draw(frame_buffer_t& previous) { glActiveTexture(GL_TEXTURE0); - previous.getBuffer().getTexture(frame_buffer_t::attachment_t::COLOR0).bind(); + previous.getTexture(frame_buffer_t::attachment_t::COLOR0).bind(); + GLenum buf[]{static_cast(frame_buffer_t::attachment_t::COLOR0)}; + glDrawBuffers(1, buf); } void pp_render_target_t::create() @@ -132,9 +158,11 @@ namespace blt::gfx void pp_render_target_t::draw() { draw_buffer.updateBuffersStorage(getWindowWidth(), getWindowHeight()); + GLenum buf[]{static_cast(frame_buffer_t::attachment_t::COLOR0)}; + glDrawBuffers(1, buf); } - void pp_outline_target::create() + void pp_outline_target_t::create() { draw_buffer.create(); draw_buffer.bind(); @@ -153,9 +181,11 @@ namespace blt::gfx frame_buffer_t::unbind(); } - void pp_outline_target::draw() + void pp_outline_target_t::draw() { draw_buffer.updateBuffersStorage(getWindowWidth(), getWindowHeight()); + const GLenum buffers[]{static_cast(frame_buffer_t::attachment_t::COLOR0), static_cast(frame_buffer_t::attachment_t::COLOR1)}; + glDrawBuffers(2, buffers); } void pp_outline_step_t::create() @@ -166,15 +196,86 @@ namespace blt::gfx shader->setInt("mask", 1); } - void pp_outline_step_t::draw(pp_step_t& previous) + void pp_outline_step_t::draw(frame_buffer_t& previous) { draw_buffer.updateBuffersStorage(getWindowWidth(), getWindowHeight()); glActiveTexture(GL_TEXTURE0); - previous.getBuffer().getTexture(frame_buffer_t::attachment_t::COLOR0).bind(); + previous.getTexture(frame_buffer_t::attachment_t::COLOR0).bind(); glActiveTexture(GL_TEXTURE1); - previous.getBuffer().getTexture(frame_buffer_t::attachment_t::COLOR1).bind(); + previous.getTexture(frame_buffer_t::attachment_t::COLOR1).bind(); shader->bind(); - auto v = manager.getScale2D(); - shader->setVec2("viewportSize", static_cast(getWindowWidth()) * (1.0f/v.x()), static_cast(getWindowHeight()) * (1.0f / v.y())); + auto v = vec2(getWindowWidth(), getWindowHeight()) * (1.0 / blt::make_vec2(manager.getScale2D())); + //BLT_TRACE_STREAM << v << '\n'; + //shader->setVec2("viewportSize", static_cast(v.x()), static_cast(v.y())); + GLenum buf[]{static_cast(frame_buffer_t::attachment_t::COLOR0)}; + glDrawBuffers(1, buf); + } + + void pp_blur_step_t::create() + { + draw_buffer = frame_buffer_t::make_render_texture(getWindowWidth(), getWindowHeight()); + shader = pp_engine_t::createShader(shader_gaussian_blur_frag); + } + + void pp_blur_step_t::draw(frame_buffer_t& previous) + { + draw_buffer.updateBuffersStorage(getWindowWidth(), getWindowHeight()); + shader->bind(); + shader->setVec4i("size", {getWindowWidth(), getWindowHeight(), x_blur, y_blur}); + glActiveTexture(GL_TEXTURE0); + previous.getTexture(from).bind(); + GLenum buf[]{static_cast(to)}; + glDrawBuffers(1, buf); + } + + void pp_blur_step_inplace_t::create() + { + draw_buffer = frame_buffer_t::make_render_texture(getWindowWidth(), getWindowHeight()); + shader = pp_engine_t::createShader(shader_gaussian_blur_frag); + shader_pass = pp_engine_t::createShader(shader_pp_screen_frag); + } + + void pp_blur_step_inplace_t::draw(frame_buffer_t& previous) + { + draw_buffer.updateBuffersStorage(getWindowWidth(), getWindowHeight()); + shader->bind(); + //auto v = vec2(getWindowWidth(), getWindowHeight()) * (1.0 / blt::make_vec2(manager.getScale2D())); + auto v = vec2(getWindowWidth(), getWindowHeight()); + shader->setVec4i("size", {static_cast(v.x()), static_cast(v.y()), x_blur, y_blur}); + glActiveTexture(GL_TEXTURE0); + previous.getTexture(from).bind(); + //GLenum buf[]{static_cast(to)}; + GLenum buf[]{static_cast(frame_buffer_t::attachment_t::COLOR0)}; + glDrawBuffers(1, buf); + draw_buffer.bind(); + glClear(GL_COLOR_BUFFER_BIT); + } + + void pp_blur_step_inplace_t::post_draw(frame_buffer_t& previous) + { + //draw_buffer.blitTexture(previous, 0, 0, 0, 0, GL_NEAREST, from, to); + previous.bind(); + GLenum buf[]{static_cast(to)}; + glDrawBuffers(1, buf); + glClear(GL_COLOR_BUFFER_BIT); + shader_pass->bind(); + glActiveTexture(GL_TEXTURE0); + draw_buffer.getTexture(frame_buffer_t::attachment_t::COLOR0).bind(); + pp_engine_t::render_quad(); + } + + void pp_expansion_step_inplace_t::create() + { + shader = pp_engine_t::createShader(shader_multiplier_frag); + } + + void pp_expansion_step_inplace_t::draw(frame_buffer_t& previous) + { + shader->bind(); + shader->setVec4("multiplier", multiplier); + glActiveTexture(GL_TEXTURE0); + previous.getTexture(from).bind(); + GLenum buf[]{static_cast(to)}; + glDrawBuffers(1, buf); } } \ No newline at end of file diff --git a/src/blt/gfx/shader.cpp b/src/blt/gfx/shader.cpp index e5f0b5a..e7dfd90 100644 --- a/src/blt/gfx/shader.cpp +++ b/src/blt/gfx/shader.cpp @@ -322,6 +322,15 @@ namespace blt::gfx return *this; } + shader_base_t& shader_base_t::setVec4i(const std::string& name, const vec4i& vec) + { + if (auto i = getUniformLocation(name)) + glUniform4i(i.i, vec.x(), vec.y(), vec.z(), vec.w()); + else + BLT_WARN("Unable to find vec4i uniform variable %s", name.c_str()); + return *this; + } + shader_base_t::IntDefaultedToMinusOne shader_base_t::getUniformLocation(const std::string& name) { if (uniformVars[name]) diff --git a/src/blt/gfx/texture.cpp b/src/blt/gfx/texture.cpp index b0296b3..de0da55 100644 --- a/src/blt/gfx/texture.cpp +++ b/src/blt/gfx/texture.cpp @@ -152,10 +152,10 @@ blt::gfx::texture_file& blt::gfx::texture_file::resize(int target_width, int tar return *this; } -void blt::gfx::texture_gl::setDefaults(GLint type) const +void blt::gfx::texture_gl::setDefaults(GLint type, GLint wrap_type) const { - glTexParameteri(textureBindType, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(textureBindType, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(textureBindType, GL_TEXTURE_WRAP_S, wrap_type); + glTexParameteri(textureBindType, GL_TEXTURE_WRAP_T, wrap_type); // nearest preserves the pixely look #ifdef __EMSCRIPTEN__ glTexParameteri(textureBindType, GL_TEXTURE_MIN_FILTER, GL_NEAREST); @@ -215,7 +215,7 @@ void blt::gfx::texture_gl2D::resize(int width, int height) blt::gfx::texture_gl2D::texture_gl2D(int width, int height, GLint colorMode): texture_gl(width, height, GL_TEXTURE_2D, colorMode) { bind(); - setDefaults(GL_LINEAR); + setDefaults(GL_LINEAR, GL_CLAMP_TO_EDGE); resize(width, height); //glTexStorage2D(textureBindType, 4, colorMode, width, height); } @@ -249,13 +249,17 @@ blt::gfx::texture_gl2D_multisample::texture_gl2D_multisample(int width, int heig texture_gl(width, height, GL_TEXTURE_2D_MULTISAMPLE, colorMode), samples(samples) { bind(); - setDefaults(GL_LINEAR); + setDefaults(GL_LINEAR, GL_CLAMP_TO_EDGE); //glTexImage2DMultisample(textureBindType, samples, colorMode, width, height, GL_TRUE); glTexStorage2DMultisample(textureBindType, samples, colorMode, width, height, GL_TRUE); } void blt::gfx::texture_gl2D_multisample::resize(int width, int height) { + if (m_width == width && m_height == height) + return; + m_width = width; + m_height = height; bind(); //glTexImage2DMultisample(textureBindType, samples, textureColorMode, width, height, GL_TRUE); glTexStorage2DMultisample(textureBindType, samples, textureColorMode, width, height, GL_TRUE);